package org.streets.workflow.engine.internal;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.slf4j.Logger;
import org.streets.commons.util.BeanUtils;
import org.streets.commons.util.StringUtils;
import org.streets.workflow.engine.IActivity;
import org.streets.workflow.engine.IJoinPoint;
import org.streets.workflow.engine.ILoop;
import org.streets.workflow.engine.INode;
import org.streets.workflow.engine.IProcessDefinition;
import org.streets.workflow.engine.IProcessInstance;
import org.streets.workflow.engine.IProcessTrace;
import org.streets.workflow.engine.ISyncRouter;
import org.streets.workflow.engine.ITaskInstance;
import org.streets.workflow.engine.IToken;
import org.streets.workflow.engine.ITransition;
import org.streets.workflow.engine.IWorkItem;
import org.streets.workflow.engine.WorkflowContext;
import org.streets.workflow.engine.WorkflowEngine;
import org.streets.workflow.engine.WorkflowException;
import org.streets.workflow.engine.calendar.ICalendarService;
import org.streets.workflow.engine.condition.ConditionConstant;
import org.streets.workflow.engine.entities.ProcessInstance;
import org.streets.workflow.engine.entities.ProcessTrace;
import org.streets.workflow.engine.entities.TaskInstance;
import org.streets.workflow.engine.entities.Token;
import org.streets.workflow.engine.entities.WorkItem;
import org.streets.workflow.engine.event.EdgeEvent;
import org.streets.workflow.engine.event.IEdgeEventListener;
import org.streets.workflow.engine.event.IProcessEventListener;
import org.streets.workflow.engine.event.NodeEvent;
import org.streets.workflow.engine.event.ProcessInstanceEvent;
import org.streets.workflow.engine.event.TaskEvent;
import org.streets.workflow.engine.mem.JoinPoint;
import org.streets.workflow.engine.persistence.IWorkflowDAO;
import org.streets.workflow.engine.plugin.INodeNetExtension;
import org.streets.workflow.engine.task.DefaultDynamicTaskAssignor;
import org.streets.workflow.engine.task.ITaskEvaluator;
import org.streets.workflow.engine.task.ITaskEventListener;
import org.streets.workflow.engine.task.ITaskHandler;
import org.streets.workflow.model.Duration;
import org.streets.workflow.model.WFDataField;
import org.streets.workflow.model.WFElement;
import org.streets.workflow.model.WFEventListener;
import org.streets.workflow.model.WFFormTask;
import org.streets.workflow.model.WFProcess;
import org.streets.workflow.model.WFTask;
import org.streets.workflow.model.net.WFActivity;
import org.streets.workflow.model.net.WFEndNode;
import org.streets.workflow.model.net.WFNode;
import org.streets.workflow.model.net.WFSyncRouter;
import org.streets.workflow.model.net.WFTransition;


/**
 * @author chennieyun,dzb 
 */
public class WorkflowEngineImpl implements WorkflowEngine {
    
    protected Logger logger;
	protected WorkflowContext context = null;
	protected DefaultDynamicTaskAssignor dynamicHandler = null;
	protected boolean inWithdrawOrRejectOperation = false;
	protected Map<String,Object> attributes = new HashMap<String,Object>();

	//-------------------------------------------------------
	//FIXME dzb where to put these instances ???
	protected ITaskHandler formTaskRunner = null;
	protected ITaskHandler subflowTaskRunner = null;
	protected ITaskHandler toolTaskRunner = null;
	protected ITaskEvaluator formTaskEvaluator = null;
	protected ITaskEvaluator toolTaskEvaluator = null;
	protected ITaskEvaluator subflowTaskEvaluator = null;
//	protected ITaskEventListener taskEventListener = null;
	//-------------------------------------------------------

    /**
     * 工作流网实例
     * map的key的组成规则：流程定义ID_V_版本号
     */
    private HashMap<String, NodeNet> netInstanceMap = new HashMap<String, NodeNet>();
    /**
     * wangmj spring 初始化的时候将扩展属性注入到这个map中
     * 内核扩展对象
     */
    private Map<String, List<INodeNetExtension>> kernelExtensions = new HashMap<String, List<INodeNetExtension>>();
 
    	
	//-------------------------------------------------------

    public List<IProcessDefinition> getAllDefinitions() {
        
        return context.getPersistenceService().findAllDefinitions();
    }

    public IProcessDefinition getDefinition(String definitionId, Integer definitionVersion) {
        
        return context.getPersistenceService().findDefinition(definitionId, definitionVersion);
    }
	
	//-------------------------------------------------------
    
    /**
     * 在获取工作流网实例的时候，调用createNetInstance方法，创建实例
     * @param processId  流程定义ID
     * @param version    流程版本号
     * @return
     * @throws KernelException
     */
    public NodeNet getNetInstance(WFProcess processModel, int version) throws WorkflowException {
        
        NodeNet netInstance = this.netInstanceMap.get(processModel.getId() + "_V_" + version);
        
        if (netInstance == null) {
        	
            String validateMsg =  processModel.validate();//校验工作流定义是否有效            
            if (validateMsg != null){
                throw new WorkflowException(validateMsg);
            }
            
            netInstance = new NodeNet(processModel, kernelExtensions);

            netInstanceMap.put(processModel.getId() + "_V_" + version, netInstance);
        }
        return netInstance;
    }

    /**
     * 清空所有工作流网的实例
     */
    public void clearAllNetInstance() {
        netInstanceMap.clear();
    }
    
    //-------------------------------------------------------
    
	/**
     * 触发process instance相关的事件
     * @param e
     * @throws org.WorkflowException.engine.EngineException
     */
    protected void fireProcessInstanceEvent(IProcessInstance process, ProcessInstanceEvent e) throws WorkflowException {
        
        WFProcess wfprocess = process.getModel();
        if (wfprocess == null) {
            return;
        }

        List<WFEventListener> listeners = wfprocess.getEventListeners();
        for (WFEventListener listener : listeners) {
            Object obj = null;
			try {
				//FIXME 使用监听器管理器？
				obj = Class.forName(listener.getClassName()).newInstance();
			} catch (Exception e1) {
				e1.printStackTrace();
			} 
            if (obj != null) {
                ((IProcessEventListener) obj).onProcessEventFired(e);
            }
        }
    }

    public WorkflowEngineImpl(WorkflowContext ctx) {
        this.context = ctx;
    }

    public WorkflowContext getRuntimeContext() {
        return context;
    }

	public void setRuntimeContext(WorkflowContext ctx) {
		this.context = ctx;
	}
	
  	public boolean isInWithdrawOrRejectOperation() {
        return this.inWithdrawOrRejectOperation;
    }

    public void setWithdrawOrRejectOperationFlag(boolean b) {
        this.inWithdrawOrRejectOperation = b;
    }
    
	public DefaultDynamicTaskAssignor getDynamicHandler() {
		return dynamicHandler;
	}

    public void setDynamicHandler(DefaultDynamicTaskAssignor taskHandler) {
        this.dynamicHandler = taskHandler;
    }

	/**
	 * @return
	 */
	public DefaultDynamicTaskAssignor consumeCurrentDynamicTaskHandler() {
		DefaultDynamicTaskAssignor handler = dynamicHandler;
		this.dynamicHandler = null;
		return handler;
	}


    /**
     * 创建一个新的流程实例 (create a new process instance )
     * @param definitionId  流程定义ID
     * @param creatorId  创建人ID
     * @param hostProcessId  父流程实例ID
     * @param hostTaskId     父任务实例ID
     * @return
     * @throws WorkflowException
     */
    protected IProcessInstance create(String definitionId, String creatorId, String hostProcessId, String hostTaskId) throws WorkflowException {
                
        final IProcessDefinition pd = getDefinition(definitionId, -1);
        final WFProcess wf_process = pd.getModel();

        if (wf_process == null) {
            throw new WorkflowException( "Can not found process model definition , defintion id=[" + definitionId + "]");
        }
        
        ProcessInstance t_process =  new ProcessInstance();

        t_process.setCreatorId(creatorId);
        t_process.setModel(wf_process);
        t_process.setState(IProcessInstance.INITIALIZED);       
        t_process.setVersion(pd.getDefinitionVersion());
        t_process.setCreatedTime(new Date(System.currentTimeMillis()));
        t_process.setParentId(hostProcessId);
        t_process.setParentTaskId(hostTaskId);
        
        context.getPersistenceService().saveOrUpdateProcess(t_process);
        
        
        // 初始化流程变量      
        List<WFDataField> datafields = wf_process.getDataFields();
        for (int i = 0; datafields != null && i < datafields.size(); i++) {
            WFDataField df =  datafields.get(i);
            if (df.getDataType().equals(WFDataField.STRING)) {
                if (df.getInitialValue() != null) {
                    t_process.setVariable(df.getName(), df.getInitialValue());
                } else {
                    t_process.setVariable(df.getName(), "");
                }
            } else if (df.getDataType().equals(WFDataField.INTEGER)) {
                if (df.getInitialValue() != null) {
                    try {
                        Integer intValue = new Integer(df
                                .getInitialValue());
                        t_process.setVariable(df.getName(), intValue);
                    } catch (Exception e) {
                    }
                } else {
                    t_process.setVariable(df.getName(), new Integer(0));
                }
            } else if (df.getDataType().equals(WFDataField.LONG)) {
                if (df.getInitialValue() != null) {
                    try {
                        Long longValue = new Long(df.getInitialValue());
                        t_process.setVariable(df.getName(), longValue);
                    } catch (Exception e) {
                    }
                } else {
                    t_process.setVariable(df.getName(), new Long(0));
                }
            } else if (df.getDataType().equals(WFDataField.FLOAT)) {
                if (df.getInitialValue() != null) {
                    Float floatValue = new Float(df.getInitialValue());
                    t_process.setVariable(df.getName(), floatValue);
                } else {
                    t_process.setVariable(df.getName(), new Float(0));
                }
            } else if (df.getDataType().equals(WFDataField.DOUBLE)) {
                if (df.getInitialValue() != null) {
                    Double doubleValue = new Double(df
                            .getInitialValue());
                    t_process.setVariable(df.getName(), doubleValue);
                } else {
                    t_process.setVariable(df.getName(), new Double(0));
                }
            } else if (df.getDataType().equals(WFDataField.BOOLEAN)) {
                if (df.getInitialValue() != null) {
                    Boolean booleanValue = new Boolean(df
                            .getInitialValue());
                    t_process.setVariable(df.getName(), booleanValue);
                } else {
                    t_process.setVariable(df.getName(), Boolean.FALSE);
                }
            } else if (df.getDataType().equals(WFDataField.DATETIME)) {
                // TODO 需要完善一下
                if (df.getInitialValue() != null
                        && df.getDataPattern() != null) {
                    try {
                        SimpleDateFormat dFormat = new SimpleDateFormat(
                                df.getDataPattern());
                        Date dateTmp = new Date((dFormat.parse(df.getInitialValue()).getTime()));
                        t_process.setVariable(df.getName(), dateTmp);
                    } catch (Exception e) {
                        t_process.setVariable(df.getName(), null);
                        e.printStackTrace();
                    }
                } else {
                    t_process.setVariable(df.getName(), null);
                }
            }
        }
        return t_process;
    }
	   
    /**
     * 创建流程实例
     */
    public IProcessInstance create(String definitionId, String creatorId) throws WorkflowException {
        return create(definitionId, creatorId, null, null);
    }

    public IProcessInstance create(String definitionId, ITaskInstance task) throws WorkflowException {
        return create(
            definitionId,
            "Task["+task.getId()+"]", 
            task.getProcess().getId(), 
            task.getId());
    }

    /**
     * 流程实例开始运行！
     * @throws WorkflowException
     */
    public void run(IProcessInstance processInstance) throws WorkflowException {
        
        if (processInstance.getState().intValue() != IProcessInstance.INITIALIZED) {
            throw new WorkflowException(processInstance.getId(),
                processInstance.getModel(),
                processInstance.getDefinitionId(), "The state of the process instance is " + processInstance.getState() + ",can not run it ");
        }

        NodeNet netInstance = getNetInstance(processInstance.getModel(), processInstance.getVersion());
        if (netInstance == null) {
            throw new WorkflowException(processInstance.getId(),
                processInstance.getModel(),
                processInstance.getDefinitionId(), "The net instance for the  workflow process [Id=" + processInstance.getDefinitionId() + "] is Not found");
        }
        //触发事件
        ProcessInstanceEvent event = new ProcessInstanceEvent();
        event.setEventType(ProcessInstanceEvent.BEFORE_PROCESS_INSTANCE_RUN);
        event.setSource(processInstance);
        fireProcessInstanceEvent(processInstance, event);
        //设置运行状态
        ((ProcessInstance)processInstance).setState(IProcessInstance.RUNNING);
        ((ProcessInstance)processInstance).setStartedTime(context.getCalendarService().getSysDate());
        context.getPersistenceService().saveOrUpdateProcess(processInstance);
        
        //----------------------
        // Call net to start
        if (netInstance.getStartNode() == null) {
            throw new WorkflowException(processInstance, processInstance.getModel(), "Error:NetInstance is illegal ，the startNodeInstance can NOT be NULL ");
        }

        Token token = new Token();//初始化token
        token.setAlive(true); //活动的
        token.setProcess(processInstance); //对应流程实例
        token.setValue(netInstance.getStartNode().getVolume()); //token容量
        token.setStepNumber(0); //步骤号，开始节点的第一步默认为0
        token.setFromActivityId(IToken.FROM_START_NODE); //从哪个节点来 "FROM_START_NODE" 规定的节点。

        ////启动开始节点 注意这里并没有保存token
        fireStartNode(netInstance.getStartNode(), token);
    }


    public void suspend(IProcessInstance processInstance) throws WorkflowException {
        if (processInstance.getState() == IProcessInstance.COMPLETED || processInstance.getState() == IProcessInstance.CANCELED) {
            throw new WorkflowException(processInstance, processInstance.getModel(), "The process instance can not be suspended,the state of this process instance is " + processInstance.getState());
        }
        if (processInstance.isSuspended()) {
            return;
        }
        IWorkflowDAO persistenceService = getRuntimeContext().getPersistenceService();
        persistenceService.suspendProcess(processInstance);
    }

    public void restore(IProcessInstance processInstance) throws WorkflowException {
        if (processInstance.getState() == IProcessInstance.COMPLETED || processInstance.getState() == IProcessInstance.CANCELED) {
            throw new WorkflowException(processInstance, processInstance.getModel(), "The process instance can not be restored,the state of this process instance is " + processInstance.getState());
        }
        if (!processInstance.isSuspended()) {
            return;
        }

        IWorkflowDAO persistenceService = getRuntimeContext().getPersistenceService();
        persistenceService.restoreProcess(processInstance);

    }


    public void abort(IProcessInstance processInstance) throws WorkflowException {
        if (processInstance.getState().intValue() == IProcessInstance.COMPLETED || processInstance.getState().intValue() == IProcessInstance.CANCELED) {
            throw new WorkflowException(processInstance, processInstance.getModel(), "The process instance can not be aborted,the state of this process instance is " + processInstance.getState());
        }
        IWorkflowDAO persistenceService = getRuntimeContext().getPersistenceService();
        persistenceService.abortProcess(processInstance);
    }

    /**
     * 正常结束工作流
     * 1、首先检查有无活动的token,如果有则直接返回，如果没有则结束当前流程
     * 2、执行结束流程的操作，将state的值设置为结束状态
     * 3、然后检查parentTaskInstanceId是否为null，如果不为null则，调用父taskinstance的complete操作。
     * @throws RuntimeException
     */
    public void complete(IProcessInstance processInstance) throws WorkflowException  {
        //1、判断是否所有的EndeNodeInstance都到达终态，如果没有到达，则直接返回。
        //2、执行compelete操作，
        //3、触发after complete事件processInstance
        //4、返回主流程
        
        List<IToken> tokens = context.getPersistenceService().findTokens(processInstance.getId(), null);
        boolean canBeCompleted = true;
        for (int i = 0; tokens != null && i < tokens.size(); i++) {
            IToken token = tokens.get(i);
            if (token.isAlive()) {
                canBeCompleted = false;
                break;
            }
        }
        if (!canBeCompleted) {
            return;
        }

        ((ProcessInstance)processInstance).setState(IProcessInstance.COMPLETED);
        //记录结束时间
        ((ProcessInstance)processInstance).setEndTime(context.getCalendarService().getSysDate());
        context.getPersistenceService().saveOrUpdateProcess(processInstance);
        
        //删除所有的token
        for (int i = 0; tokens != null && i < tokens.size(); i++) {
            Token token = (Token)tokens.get(i);
            context.getPersistenceService().deleteToken(token);
        }

        //触发事件
        ProcessInstanceEvent event = new ProcessInstanceEvent();
        event.setEventType(ProcessInstanceEvent.AFTER_PROCESS_INSTANCE_COMPLETE);
        event.setSource(processInstance);
        fireProcessInstanceEvent(processInstance, event);
        if (StringUtils.isNotEmpty(processInstance.getParentTaskId())) {
            ITaskInstance taskInstance = context.getPersistenceService().findAliveTask(processInstance.getParentTaskId());
            complete(taskInstance);
        }        
    }


	private IWorkItem findWorkItem(String id) {	    
	    IWorkItem workItem = context.getPersistenceService().findWorkItem(id);
	    return workItem;
	}

	public ITaskInstance findTask(String id) {
	    ITaskInstance task = context.getPersistenceService().findTask(id);
	    return task;
	}

	public List<IWorkItem> findTodoWorkItems(final String actorId) {
		List<IWorkItem> result =  context.getPersistenceService().findTodoWorkItems(actorId);
		return result;
	}

	public List<IWorkItem> findTodoWorkItems(final String actorId, 
	        final String processInstanceId) {
		List<IWorkItem> result = context.getPersistenceService().findTodoWorkItems(actorId, processInstanceId);
		return result;
	}

	public List<IWorkItem> findTodoWorkItems(final String actorId,
			final String definitionId, final String taskModelId) {

	    List<IWorkItem> result = context.getPersistenceService().findTodoWorkItems(
            actorId, definitionId, taskModelId);
		return result;
	}
//    /**
//     * 签收工作项。如果任务实例的分配模式是ANY，则同一个任务实例的其他工作项将被删除。
//     * 如果任务是里的分配模式是ALL，则此操作不影响同一个任务实例的其他工作项的状态。<br/>
//     * 如果签收成功，则返回一个新的IWorkItem对象，并且更新当前WorkItem对象的状态修改成RUNNING状态，
//     * 更新ClaimedTime属性值。<br/>
//     * 如果签收失败，则返回null，且当前WorkItem的状态被修改为CANCELED<br/>
//     * 例如：同一个TaskInstance被分配给Actor_1和Actor_2，且分配模式是ANY，即便Actor_1和Actor_2同时执行
//     * 签收操作，也必然有一个人签收失败。系统对这种竞争性操作进行了同步。
//     * @throws org.WorkflowException.engine.EngineException
//     * @throws org.fireflow.kenel.KenelException
//     * @return 如果签收成功，则返回一个新的IWorkItem对象；否则返回null
//     */
//	public IWorkItem claimWorkItem(final String workItemId)
//			throws WorkflowException {
//		IWorkItem result = null;
//		IWorkItem wi = this.findWorkItem(workItemId);
//		result = claimWorkItem(wi);
//		return result;
//	}

    /**
     * 结束当前WorkItem；并由工作流引擎根据流程定义决定下一步操作。引擎的执行规则如下<br/>
     * 1、工作流引擎首先判断该WorkItem对应的TaskInstance是否可以结束。
     * 如果TaskInstance的assignment策略为ANY，或者，assignment策略为ALL且它所有的WorkItem都已经完成
     * 则结束当前TaskInstance<br/>
     * 2、判断TaskInstance对应的ActivityInstance是否可以结束。如果ActivityInstance的complete strategy
     * 为ANY，或者，complete strategy为ALL且他的所有的TaskInstance都已经结束，则结束当前ActivityInstance<br/>
     * 3、根据流程定义，启动下一个Activity，并创建相关的TaskInstance和WorkItem
     * @throws org.WorkflowException.engine.EngineException
     */
	public void completeWorkItem(String workItemId) throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		complete(wi, null, "auto claim");

	}

    /**
     * 结束当前WorkItem；并由工作流引擎根据流程定义决定下一步操作。引擎的执行规则如下<br/>
     * 1、工作流引擎首先判断该WorkItem对应的TaskInstance是否可以结束。
     * 如果TaskInstance的assignment策略为ANY，或者，assignment策略为ALL且它所有的WorkItem都已经完成
     * 则结束当前TaskInstance<br/>
     * 2、判断TaskInstance对应的ActivityInstance是否可以结束。如果ActivityInstance的complete strategy
     * 为ANY，或者，complete strategy为ALL且他的所有的TaskInstance都已经结束，则结束当前ActivityInstance<br/>
     * 3、根据流程定义，启动下一个Activity，并创建相关的TaskInstance和WorkItem
     * @throws org.WorkflowException.engine.EngineException
	 */
	public void completeWorkItem(String workItemId, String comments)
			throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		complete(wi, null, comments);
	}
    /**
     * 结束当前WorkItem；并由工作流引擎根据流程定义决定下一步操作。引擎的执行规则如下<br/>
     * 1、工作流引擎首先判断该WorkItem对应的TaskInstance是否可以结束。
     * 如果TaskInstance的assignment策略为ANY，或者，assignment策略为ALL且它所有的WorkItem都已经完成
     * 则结束当前TaskInstance<br/>
     * 2、判断TaskInstance对应的ActivityInstance是否可以结束。如果ActivityInstance的complete strategy
     * 为ANY，或者，complete strategy为ALL且他的所有的TaskInstance都已经结束，则结束当前ActivityInstance<br/>
     * 3、根据流程定义，启动下一个Activity，并创建相关的TaskInstance和WorkItem
     * @param dynamicAssignmentHandler 通过动态分配句柄指定下一个环节的操作者。
     * @param comments 备注信息
     * @throws WorkflowException
     */
	public void completeWorkItem(String workItemId, DefaultDynamicTaskAssignor dynamicAssignmentHandler, String comments)
			throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		complete(wi, dynamicAssignmentHandler, comments);
	}

	public void completeWorkItemAndJumpTo(String workItemId, String targetActivityId) throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		jumpTo(wi, targetActivityId);
	}

	public void completeWorkItemAndJumpTo(String workItemId,
			String targetActivityId, String comments) throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		jumpTo(wi, targetActivityId, comments);
	}

	public void completeWorkItemAndJumpTo(String workItemId,
			String targetActivityId,
			DefaultDynamicTaskAssignor dynamicAssignmentHandler, String comments)
			throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		jumpTo(wi, targetActivityId, dynamicAssignmentHandler, comments);

	}

	public void completeWorkItemAndJumpToEx(String workItemId,
			String targetActivityId,
			DefaultDynamicTaskAssignor dynamicAssignmentHandler, String comments)
			throws WorkflowException {
		IWorkItem wi = this.findWorkItem(workItemId);
		jumpToEx(wi, targetActivityId, dynamicAssignmentHandler, comments);
	}

    /**
     * 结束当前WorkItem；并由工作流引擎根据流程定义决定下一步操作。引擎的执行规则如下<br/>
     * 1、工作流引擎首先判断该WorkItem对应的TaskInstance是否可以结束。
     * 如果TaskInstance的assignment策略为ANY，或者，assignment策略为ALL且它所有的WorkItem都已经完成
     * 则结束当前TaskInstance<br/>
     * 2、判断TaskInstance对应的ActivityInstance是否可以结束。如果ActivityInstance的complete strategy
     * 为ANY，或者，complete strategy为ALL且他的所有的TaskInstance都已经结束，则结束当前ActivityInstance<br/>
     * 3、根据流程定义，启动下一个Activity，并创建相关的TaskInstance和WorkItem
     * @param dynamicTaskHandler 通过动态分配句柄指定下一个环节的操作者。
     * @param comments 备注信息
     * @throws WorkflowException
     */
    public void complete(IWorkItem workItem, DefaultDynamicTaskAssignor dynamicTaskHandler, String comments)
            throws WorkflowException {
        if (workItem.getState().intValue() != IWorkItem.RUNNING) {
            TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();

            throw new WorkflowException(thisTaskInst.getProcess().getId(), thisTaskInst.getProcess().getModel(),
                    thisTaskInst.getTaskModelId(),
                    "Complete work item failed . The state of the work item [id=" + workItem.getId() + "] is " + workItem.getState());
        }       
        
        if (dynamicTaskHandler!=null) {
            setDynamicHandler(dynamicTaskHandler);
        }
        
        completeWorkItem(workItem, null, comments);
    }
    
    /**
     * 签收工作项。如果任务实例的分配模式是ANY，则同一个任务实例的其他工作项将被删除。
     * 如果任务是里的分配模式是ALL，则此操作不影响同一个任务实例的其他工作项的状态。<br/>
     * 如果签收成功，则返回一个新的IWorkItem对象，并且更新当前WorkItem对象的状态修改成RUNNING状态，
     * 更新ClaimedTime属性值。<br/>
     * 如果签收失败，则返回null，且当前WorkItem的状态被修改为CANCELED<br/>
     * 例如：同一个TaskInstance被分配给Actor_1和Actor_2，且分配模式是ANY，即便Actor_1和Actor_2同时执行
     * 签收操作，也必然有一个人签收失败。系统对这种竞争性操作进行了同步。
     * @throws org.WorkflowException.engine.EngineException
     * @throws org.fireflow.kenel.KenelException
     * @return 如果签收成功，则返回一个新的IWorkItem对象；否则返回null
     */
    public IWorkItem claimWorkItem(IWorkItem workItem) throws WorkflowException {

        IWorkItem newWorkItem = claimWorkItem(workItem.getId(), workItem.getTask().getId());
        
        if (newWorkItem != null){
            ((WorkItem)workItem).setState(newWorkItem.getState());
            ((WorkItem)workItem).setClaimedTime(newWorkItem.getClaimedTime());            
        } else {
            ((WorkItem)workItem).setState(IWorkItem.CANCELED);
        }
        
        return newWorkItem;
    }


    /**
     * 结束当前WorkItem，跳转到指定的Activity<br/>
     * 只有满足如下条件的情况下，该方法才能成功执行，否则抛出EngineException，流程状态恢复到调用该方法之前的状态。<br/>
     * 1)当前Activity和即将启动的Acitivty必须在同一个执行线上<br/>
     * 2)当前Task的assignment为Task.ANY。或者当前Task的assignment为Task.ALL(汇签)，且本WorkItem结束后可以使得TaskInstance结束；与之相反的情况是，
     * 尚有其他参与汇签的操作者没有完成其工作项，这时engine拒绝跳转操作<br/>
     * 3)当前TaskInstance结束后,可以使得当前的ActivityInstance结束。与之相反的情况是，当前Activity包含了多个Task，且Activity的Complete Strategy是ALL，
     * 尚有其他的TaskInstance仍然处于活动状态，这种情况下执行jumpTo操作会被拒绝。
     * @param targetActivityId 下一个环节的ActivityId
     * @throws org.WorkflowException.engine.EngineException 
     * @throws org.fireflow.kenel.KenelException
     */
    public void jumpTo(IWorkItem workItem, String activityId) throws WorkflowException {
        jumpTo(workItem, activityId, null, workItem.getComments());
    }

    /**
     * 结束当前WorkItem，跳转到指定的Activity<br/>
     * 只有满足如下条件的情况下，该方法才能成功执行，否则抛出EngineException，流程状态恢复到调用该方法之前的状态。<br/>
     * 1)当前Activity和即将启动的Acitivty必须在同一个执行线上<br/>
     * 2)当前Task的assignment为Task.ANY。或者当前Task的assignment为Task.ALL(汇签)，且本WorkItem结束后可以使得TaskInstance结束；与之相反的情况是，
     * 尚有其他参与汇签的操作者没有完成其工作项，这时engine拒绝跳转操作<br/>
     * 3)当前TaskInstance结束后,可以使得当前的ActivityInstance结束。与之相反的情况是，当前Activity包含了多个Task，且Activity的Complete Strategy是ALL，
     * 尚有其他的TaskInstance仍然处于活动状态，这种情况下执行jumpTo操作会被拒绝。
     * @param targetActivityId 下一个环节的id
     * @param comments 备注信息
     * @throws WorkflowException
     */
    public void jumpTo(IWorkItem workItem, String activityId, String comments) throws WorkflowException {
        jumpTo(workItem, activityId, null, comments);
    }
 
    /**
     * 结束当前WorkItem，跳转到指定的Activity<br/>
     * 只有满足如下条件的情况下，该方法才能成功执行，否则抛出EngineException，流程状态恢复到调用该方法之前的状态。<br/>
     * 1)当前Activity和即将启动的Acitivty必须在同一个执行线上<br/>
     * 2)当前Task的assignment为Task.ANY。或者当前Task的assignment为Task.ALL(汇签)，且本WorkItem结束后可以使得TaskInstance结束；与之相反的情况是，
     * 尚有其他参与汇签的操作者没有完成其工作项，这时engine拒绝跳转操作<br/>
     * 3)当前TaskInstance结束后,可以使得当前的ActivityInstance结束。与之相反的情况是，当前Activity包含了多个Task，且Activity的Complete Strategy是ALL，
     * 尚有其他的TaskInstance仍然处于活动状态，这种情况下执行jumpTo操作会被拒绝。
     * @param targetActivityId 下一个环节的id
     * @param dynamicAssignmentHandler 可以通过该参数指定下一个环节的Actor，如果这个参数不为空，则引擎忽略下一个环节的Task定义中的AssignmentHandler
     * @param comments 备注信息
     * @throws org.WorkflowException.engine.EngineException
     * @throws org.fireflow.kenel.KenelException
     */
    public void jumpTo(IWorkItem workItem, String targetActivityId, DefaultDynamicTaskAssignor dynamicAssignmentHandler, String comments) throws WorkflowException {
        if (dynamicAssignmentHandler!=null){
            setDynamicHandler(dynamicAssignmentHandler);
        }        
        completeWorkItemAndJumpTo(workItem, targetActivityId, comments);
    }
    
    /**
     * 超级自由流 （使用说明参考jumpTo ）
     * @param targetActivityId
     * @param dynamicAssignmentHandler
     * @param comments
     * @throws WorkflowException
     */
    public void jumpToEx(IWorkItem workItem, String targetActivityId, DefaultDynamicTaskAssignor dynamicAssignmentHandler, String comments) throws WorkflowException {
        if (dynamicAssignmentHandler!=null){
            setDynamicHandler(dynamicAssignmentHandler);
        }
        completeWorkItemAndJumpToEx(workItem, targetActivityId, comments);
    }   
	
	public IProcessInstance findProcessInstance(final String id) {
	    IWorkflowDAO persistenceService = context.getPersistenceService();
	    IProcessInstance processInstance = persistenceService.findProcess(id, false);
	    return processInstance;
	}

	public List<IProcessInstance> findProcessInstances(final String processId) {
	    List<IProcessInstance> processInstances = context.getPersistenceService().findProcesses(processId);
	    return processInstances;
	}

	public List<IProcessInstance> findProcessInstances(
			final String processId, final Integer version) {
	    
	    List<IProcessInstance> processInstances = context.getPersistenceService().findProcesses(
            processId, version);
	    
	    return processInstances;
	}

	public List<ITaskInstance> findTasks(
			final String processInstanceId, final String activityId) {
	    
	    List<ITaskInstance> tasks = context.getPersistenceService().findTasks(
            processInstanceId, activityId);
	    return tasks;
	}

    /**
     * 将工作项位派给其他人，自己的工作项变成CANCELED状态。返回新创建的WorkItem.
     * @param workItem 我的WorkItem
     * @param actorId 被委派的Actor的Id
     * @param comments 备注信息
     * @return 新创建的工作项
     */
	public IWorkItem reassignWorkItemTo(String workItemId, String actorId)
			throws WorkflowException {
	    
		IWorkItem workItem = this.findWorkItem(workItemId);
		return reasignWorkItemTo(workItem, actorId, "No comments");
	}

    /**
     * 将工作项位派给其他人，自己的工作项变成CANCELED状态。返回新创建的WorkItem.
     * @param workItem 我的WorkItem
     * @param actorId 被委派的Actor的Id
     * @param comments 备注信息
     * @return 新创建的工作项
     */
	public IWorkItem reassignWorkItemTo(String workItemId, String actorId,
			String comments) throws WorkflowException {
		IWorkItem workItem = this.findWorkItem(workItemId);
		return reasignWorkItemTo(workItem,actorId, comments);
	}


    private IWorkItem reasignWorkItemTo(IWorkItem workItem, String actorId, String comments) {
        WorkItem newWorkItem = new WorkItem();
        BeanUtils.copy(workItem, newWorkItem);
        newWorkItem.setId(null); 
        newWorkItem.setActorId(actorId);
        newWorkItem.setCreatedTime(context.getCalendarService().getSysDate());
        context.getPersistenceService().saveOrUpdateWorkItem(newWorkItem);

        ((WorkItem) workItem).setState(IWorkItem.CANCELED);
        ((WorkItem) workItem).setEndTime(context.getCalendarService().getSysDate());
        ((WorkItem) workItem).setComments(comments);
        context.getPersistenceService().saveOrUpdateWorkItem(workItem);
        return newWorkItem;
    }
//
//    /**
//     * 执行“拒收”操作，可以对已经签收的或者未签收的WorkItem拒收。<br/>
//     * 该操作必须满足如下条件：<br/>
//     * 1、前驱环节中没有没有Tool类型和Subflow类型的Task；<br/>
//     * 2、没有和当前TaskInstance并行的其他TaskInstance；<br/>
//     * 该方法和IWorkflowSession.rejectWorkItem(String workItemId)等价。
//     * @throws WorkflowException
//     */
//	public void rejectWorkItem(String workItemId) throws WorkflowException {
//		IWorkItem workItem = this.findWorkItem(workItemId);
//		rejectWorkItem(workItem, "No comments");
//	}
//
//    /**
//     * 执行“拒收”操作，可以对已经签收的或者未签收的WorkItem拒收。<br/>
//     * 该操作必须满足如下条件：<br/>
//     * 1、前驱环节中没有没有Tool类型和Subflow类型的Task；<br/>
//     * 2、没有合当前TaskInstance并行的其他TaskInstance；<br/>
//     * 该方法和IWorkflowSession.rejectWorkItem(String workItemId,String comments)等价。
//     * @param comments 备注信息，将被写入workItem.comments字段。
//     * @throws WorkflowException
//     */
//	public void rejectWorkItem(String workItemId, String comments)
//			throws WorkflowException {
//		IWorkItem workItem = this.findWorkItem(workItemId);
//		rejectWorkItem(workItem, comments);
//	}

	/* (non-Javadoc)
	 * @see org.fireflow.engine.IWorkflowSession#restoreTaskInstance(java.lang.String)
	 */
	public ITaskInstance restoreTaskInstance(String taskInstanceId)
			throws WorkflowException {
		ITaskInstance taskInst = this.findTask(taskInstanceId);
		restore(taskInst);
		return taskInst;
	}

	/* (non-Javadoc)
	 * @see org.fireflow.engine.IWorkflowSession#suspendTaskInstance(java.lang.String)
	 */
	public ITaskInstance suspendTaskInstance(String taskInstanceId)
			throws WorkflowException {
		ITaskInstance taskInst = this.findTask(taskInstanceId);
		suspend(taskInst);
		return taskInst;
	}

    /**
     * 撤销刚才执行的Complete动作，系统将创建并返回一个新的Running状态的WorkItem

     * 对已经结束的工作项执行取回操作<br/>
     * 只有满足如下约束才能正确执行取回操作：<br/>
     * 1) 下一个Activity只有Form类型的Task,没有Tool类型和Subflow类型的Task</br>
     * 2) 下一个环节的所有WorkItem还没有被签收，都处于Initialized状态，<br/>
     * 如果在本WorkItem成功执行了jumpTo操作或者loopTo操作，只要满足上述条件，也可以
     * 成功执行withdraw。<br/>
     * 该方法和IWorkflowSession.withdrawWorkItem(String workItemId)等价。
     * @return 如果取回成功，则创建一个新的WorkItem 并返回该WorkItem
     * @throws org.WorkflowException.engine.EngineException
 
     * @param workItem
     * @return 新创建的工作项
     * @throws org.WorkflowException.engine.EngineException
     */
//	public IWorkItem withdrawWorkItem(final String workItemId)
//			throws WorkflowException {
//		IWorkItem wi = this.findWorkItem(workItemId);
//		return withdrawWorkItem(wi);
//	}

	public void clearAttributes() {
		this.attributes.clear();
		
	}

	public Object getAttribute(String name) {
		return this.attributes.get(name);
	}

	public void removeAttribute(String name) {
		this.attributes.remove(name);
	}

	public void setAttribute(String name, Object attr) {
		this.attributes.put(name, attr);
		
	}

    private void complete(ITaskInstance task) throws WorkflowException {
        completeTaskInstance(task, null);
    }
    /**
     * 生成joinPoint 
     * @param router
     * @param token
     * @return
     * @throws WorkflowException
     */
    private IJoinPoint createJoinPoint(INode node, IToken token) throws WorkflowException {
        
        IProcessInstance processInstance = token.getProcess();
        
        int enterTransInstanceCount = node.getEnteringTransitions().size();
        
        if (enterTransInstanceCount == 0) {//检查流程定义是否合法，同步器节点必须有输入边
            throw new WorkflowException(processInstance.getId(), processInstance.getModel(),
                node.getNodeId(), "The process definition [" + processInstance.getName() + "] is invalid，the router node[" + node + "] has no entering transition");
        }
        
        IWorkflowDAO persistenceService = getRuntimeContext().getPersistenceService();
        //保存到数据库
        persistenceService.saveOrUpdateToken(token);

        IJoinPoint resultJoinPoint = null;
        resultJoinPoint = new JoinPoint();
        resultJoinPoint.setProcess(processInstance);
        resultJoinPoint.setSyncRouterId(node.getNodeId());
        
        if (enterTransInstanceCount == 1) {
            // 生成一个不存储到数据库中的JoinPoint
            resultJoinPoint.addValue(token.getValue());

            if (token.isAlive()) {
                resultJoinPoint.setAlive(true);
                resultJoinPoint.setFromActivityId(token.getFromActivityId());
            }
            
            resultJoinPoint.setStepNumber(token.getStepNumber() + 1);
            return resultJoinPoint;
            
        } else {

            int stepNumber = 0;

            List<IToken> tokensList_0 = persistenceService.findTokens(processInstance.getId(), node.getNodeId());
            Map<String,IToken> tokensMap = new HashMap<String,IToken>();
            for (int i = 0; i < tokensList_0.size(); i++) {
                IToken tmpToken = tokensList_0.get(i);
                String tmpFromActivityId = tmpToken.getFromActivityId();
                if (! tokensMap.containsKey(tmpFromActivityId)) {
                    tokensMap.put(tmpFromActivityId, tmpToken);
                } else {
                    IToken tmpToken2 = tokensMap.get(tmpFromActivityId);
                    if (tmpToken2.getStepNumber() > tmpToken.getStepNumber()) {
                        tokensMap.put(tmpFromActivityId, tmpToken2);
                    }
                }
            }

            List<IToken> tokensList = new ArrayList<IToken>(tokensMap.values());

            for (int i = 0; i < tokensList.size(); i++) {
                IToken _token = tokensList.get(i);
                resultJoinPoint.addValue(_token.getValue());
                if (_token.isAlive()) {//如果token的状态是alive
                    resultJoinPoint.setAlive(true);
                    String oldFromActivityId = resultJoinPoint.getFromActivityId();
                    if (oldFromActivityId == null || oldFromActivityId.trim().equals("")) {
                        resultJoinPoint.setFromActivityId(_token.getFromActivityId());
                    } else {
                        resultJoinPoint.setFromActivityId(oldFromActivityId + IToken.FROM_ACTIVITY_ID_SEPARATOR + _token.getFromActivityId());
                    }

                }
                if (token.getStepNumber() > stepNumber) {
                    stepNumber = token.getStepNumber();
                }
            }

            resultJoinPoint.setStepNumber(stepNumber + 1);

            return resultJoinPoint;
        }
   
    }



    private void complete(INode fromActivityInstance, INode targetActivityInstance, IToken token) throws WorkflowException {
        
        NodeEvent event2 = new NodeEvent(fromActivityInstance);
        event2.setToken(token);
        event2.setEventType(NodeEvent.NODEINSTANCE_LEAVING); //token leaving
        fromActivityInstance.fireNodeEvent(this, event2);

        token.setFromActivityId(fromActivityInstance.getNodeId());

        if (targetActivityInstance != null) {
            token.setStepNumber(token.getStepNumber() + 1);
            fireActivityNode(targetActivityInstance, token);
        } else {
            //按照定义，activity有且只有一个输出弧，所以此处只进行一次循环。
            for (int i = 0; fromActivityInstance.getLeavingTransitions() != null && i < fromActivityInstance.getLeavingTransitions().size(); i++) {
                ITransition transition = fromActivityInstance.getLeavingTransitions().get(i);
                takeTransition(transition, token);
            }
        }

        if (token.isAlive()) { 
            NodeEvent event = new NodeEvent(fromActivityInstance);
            event.setToken(token);
            event.setEventType(NodeEvent.NODEINSTANCE_COMPLETED); //token completed
            fromActivityInstance.fireNodeEvent(this, event);
        }
    }
    
    
    private void fireNode(INode node, IToken token) throws WorkflowException {
        switch (node.getNodeType()) {
        case Start:
            fireStartNode((ISyncRouter)node, token);
            break;
        case Activity:
            fireActivityNode(node, token);
            break;
        case Router:
            fireRouterNode((ISyncRouter)node, token);
            break;
        case End:
            fireEndNode((ISyncRouter)node, token);
            break;
        default:
            throw new WorkflowException(token.getProcess(), node.getNodeModel(), "");        
        }
    }
    
    private void fireStartNode(ISyncRouter node, IToken token) throws WorkflowException {
        if (!token.isAlive()) {//如果token是false，那么直接返回
            return;//
        }
        if (token.getValue() != node.getVolume()) {
            WorkflowException exception = new WorkflowException(token.getProcess(),
                node.getNodeModel(),
                    "Error:Illegal StartNodeInstance,the tokenValue MUST be equal to the volume ");
            throw exception;

        }

        token.setNodeId(node.getNodeId());//到开始节点（同步器）

        IProcessInstance processInstance = token.getProcess();//从token中获得流程实例对象

        //触发token_entered事件
        NodeEvent event1 = new NodeEvent(node);
        event1.setToken(token);
        event1.setEventType(NodeEvent.NODEINSTANCE_TOKEN_ENTERED); //token进入
        node.fireNodeEvent(this, event1);

        //触发fired事件
        NodeEvent event2 = new NodeEvent(node);
        event2.setToken(token);
        event2.setEventType(NodeEvent.NODEINSTANCE_FIRED);//token 触发
        node.fireNodeEvent(this, event2);

        //触发leaving事件
        NodeEvent event4 = new NodeEvent(node);
        event4.setToken(token);
        event4.setEventType(NodeEvent.NODEINSTANCE_LEAVING); //token 离开
        node.fireNodeEvent(this, event4);


        boolean activateDefaultCondition = true;//激活默认弧线的标志
        
        ITransition defaultTransInst = null;
        //找到所有开始节点的输出弧 
        for (int i = 0; node.getLeavingTransitions() != null && i < node.getLeavingTransitions().size(); i++) {
            ITransition transition = node.getLeavingTransitions().get(i); //开始节点的边的类型只能是transition
            String condition = transition.getEdgeModel().getCondition();
            //如果弧线的条件！=null 并且 =“default” ，那么弧线实例就是default的弧线了。
            if (condition != null && condition.equals(ConditionConstant.DEFAULT)) {
                defaultTransInst = transition;//记录default转移线，其他条件都未false，才执行它
                continue;
            }

            Token n_token = new Token(); // 产生新的token
            n_token.setAlive(true);
            n_token.setProcess(processInstance);
            n_token.setFromActivityId(token.getFromActivityId());
            n_token.setStepNumber(token.getStepNumber()+1); //步骤号+1
                        
            boolean alive = takeTransition(transition, n_token);//触发弧线的token
            if (alive) {
                activateDefaultCondition = false;
            }
        }
        
        if (defaultTransInst != null) {//如果defaultTransInst!=null ，走的是default值的弧线 
            Token n_token = new Token();
            n_token.setAlive(activateDefaultCondition);//设置token为dead
            n_token.setProcess(processInstance);
            n_token.setFromActivityId(n_token.getFromActivityId());
            n_token.setStepNumber(token.getStepNumber()+1);
            takeTransition(defaultTransInst, n_token);
        }
        
        //触发completed事件
        NodeEvent event3 = new NodeEvent(node);
        event3.setToken(token);
        event3.setEventType(NodeEvent.NODEINSTANCE_COMPLETED);
        node.fireNodeEvent(this, event3);        
    }
    
    private void fireRouterNode(ISyncRouter node, IToken tk) throws WorkflowException {
        
        IProcessInstance processInstance = ((ProcessInstance) tk.getProcess());
        //TODO 此处性能需要改善一下,20090312
        IJoinPoint joinPoint = null;
        synchronized (node) { //流程同步器需要处理并发的情况，而activity的节点不需要处理并发情况？同步器节点，可能被同时触发，activity节点不会被同时触发？
            tk.setNodeId(node.getNodeId());
            logger.debug("The weight of the Entering TransitionInstance is " + tk.getValue());
            // 触发TokenEntered事件
            NodeEvent event1 = new NodeEvent(node);
            event1.setToken(tk);
            event1.setEventType(NodeEvent.NODEINSTANCE_TOKEN_ENTERED);//token 进入
            node.fireNodeEvent(this, event1);

            //汇聚检查
            joinPoint = createJoinPoint(node, tk);
            int value = joinPoint.getValue();
            logger.debug("The volume of " + this.toString() + " is " + node.getVolume());
            logger.debug("The value of " + this.toString() + " is " + value);
            if (value > node.getVolume()) {//如果value大于同步器容量，那说明出错了
                throw new WorkflowException(processInstance, node.getNodeModel(),
                        "Error:The token count of the synchronizer-instance can NOT be  greater than  it's volumn  ");
            }
            if (value < node.getVolume()) {// 如果Value小于容量则继续等待其他弧的汇聚。 (哪些状态为dead的token到此结束，不再向下传递)
                return;  
            }
        }
        //如果汇聚点的容量和同步器节点的容量相同
        
        // Synchronize的fire条件应该只与joinPoint的value有关（value==volume），与alive无关
        NodeEvent event2 = new NodeEvent(node);
        event2.setToken(tk);
        event2.setEventType(NodeEvent.NODEINSTANCE_FIRED);
        node.fireNodeEvent(this, event2);

        //在此事件监听器中，删除原有的token
        NodeEvent event4 = new NodeEvent(node);
        event4.setToken(tk);
        event4.setEventType(NodeEvent.NODEINSTANCE_LEAVING);
        node.fireNodeEvent(this, event4);

        //首先必须检查是否有满足条件的循环，loop比transition有更高的优先级，
        //（只能够有一个loop的条件为true，流程定义的时候需要注意）
        boolean doLoop = false;//表示是否有满足条件的循环，false表示没有，true表示有。
        if (joinPoint.getAlive()) {
            IToken tokenForLoop = new Token(); // 产生新的token
            tokenForLoop.setAlive(joinPoint.getAlive());
            tokenForLoop.setProcess(processInstance);
            tokenForLoop.setStepNumber(joinPoint.getStepNumber()-1);
            tokenForLoop.setFromActivityId(joinPoint.getFromActivityId());

            for (int i = 0; i < node.getLeavingLoops().size(); i++) {
                ILoop loop = node.getLeavingLoops().get(i);
                doLoop = takeLoop(loop, tokenForLoop);
                if (doLoop) {
                    break;
                }
            }
        }
        
        if (!doLoop) {//如果没有循环，则执行transitionInstance
            //非顺序流转的需要生成新的token，
            boolean activiateDefaultCondition = true;
            ITransition defaultTransInst = null;
            for (int i = 0; node.getLeavingTransitions() != null && i < node.getLeavingTransitions().size(); i++) {
                ITransition transInst = node.getLeavingTransitions().get(i);
                String condition = transInst.getEdgeModel().getCondition();
                if (condition != null && condition.equals(ConditionConstant.DEFAULT)) {
                    defaultTransInst = transInst;
                    continue;
                }

                Token token = new Token(); // 产生新的token
                token.setAlive(joinPoint.getAlive());
                token.setProcess(processInstance);
                token.setStepNumber(joinPoint.getStepNumber());
                token.setFromActivityId(joinPoint.getFromActivityId());
                boolean alive = takeTransition(transInst, token);
                if (alive) {
                    activiateDefaultCondition = false;
                }

            }
            
            if (defaultTransInst != null) {
                Token token = new Token();
                token.setAlive(activiateDefaultCondition && joinPoint.getAlive());
                token.setProcess(processInstance);
                token.setStepNumber(joinPoint.getStepNumber());
                token.setFromActivityId(joinPoint.getFromActivityId());  
                takeTransition(defaultTransInst, token);
            }            
        }

        NodeEvent event3 = new NodeEvent(node);
        event3.setToken(tk);
        event3.setEventType(NodeEvent.NODEINSTANCE_COMPLETED); //触发同步器节点的监听事件，删除所有和同步器节点相关的token
        node.fireNodeEvent(this, event3);        
        
    }
    
    private void fireActivityNode(INode node, IToken token) throws WorkflowException {
        //触发TokenEntered事件
        NodeEvent event1 = new NodeEvent(node);
        event1.setToken(token);
        event1.setEventType(NodeEvent.NODEINSTANCE_TOKEN_ENTERED);//token 来了
        node.fireNodeEvent(this, event1);
        if (token.isAlive()) {
            //如果token是活动的，那么就保存token，并创建taskinstance
            NodeEvent event = new NodeEvent(node);
            event.setToken(token);
            event.setEventType(NodeEvent.NODEINSTANCE_FIRED);//token 被触发,创建taskinstance，等待
            node.fireNodeEvent(this, event);
        } else {
          //如果token是dead状态，那么就直接结束当前节点。
            complete(node, null, token);
        }
    }
    
    private void fireEndNode(ISyncRouter node, IToken tk) throws WorkflowException {
        IJoinPoint joinPoint = null;
        IProcessInstance processInstance = tk.getProcess();
        synchronized (node) {
            tk.setNodeId(node.getNodeId());
            logger.debug("The weight of the Entering TransitionInstance is " + tk.getValue());
            // 触发TokenEntered事件
            NodeEvent event1 = new NodeEvent(node);
            event1.setToken(tk);
            event1.setEventType(NodeEvent.NODEINSTANCE_TOKEN_ENTERED);
            node.fireNodeEvent(this, event1);

            //汇聚检查
            joinPoint = createJoinPoint(node, tk);// JoinPoint由谁生成比较好？
            int value = joinPoint.getValue();

            logger.debug("The volume of " + this.toString() + " is " + node.getVolume());
            logger.debug("The value of " + this.toString() + " is " + value);
            if (value > node.getVolume()) {
                throw new WorkflowException(processInstance,
                        node.getNodeModel(),
                        "Error:The token count of the synchronizer-instance can NOT be  greater than  it's volumn  ");
            }
            // 如果Value小于容量则继续等待其他弧的汇聚
            if (value < node.getVolume()) {
                return;
            }
        }

        NodeEvent event2 = new NodeEvent(node);
        event2.setToken(tk);
        event2.setEventType(NodeEvent.NODEINSTANCE_FIRED);
        node.fireNodeEvent(this, event2);
        
        //在此事件监听器中，删除原有的token
        NodeEvent event4 = new NodeEvent(node);
        event4.setToken(tk);
        event4.setEventType(NodeEvent.NODEINSTANCE_LEAVING);
        node.fireNodeEvent(this, event4);
        
        //首先必须检查是否有满足条件的循环
        boolean doLoop = false;//表示是否有满足条件的循环，false表示没有，true表示有。

        if (joinPoint.getAlive()) {

            IToken tokenForLoop = null;

            tokenForLoop = new Token(); // 产生新的token
            tokenForLoop.setAlive(joinPoint.getAlive());
            tokenForLoop.setProcess(processInstance);
            tokenForLoop.setStepNumber(joinPoint.getStepNumber()-1);
            tokenForLoop.setFromActivityId(joinPoint.getFromActivityId());

            for (int i = 0; i < node.getLeavingLoops().size(); i++) {                
                ILoop loop = node.getLeavingLoops().get(i);
                doLoop = takeLoop(loop, tokenForLoop);
                if (doLoop) {
                    break;
                }
            }
        }

        if (! doLoop){
            NodeEvent event3 = new NodeEvent(node);
            event3.setToken(tk);
            event3.setEventType(NodeEvent.NODEINSTANCE_COMPLETED);
            node.fireNodeEvent(this, event3);
        }        
    }
    
    private boolean takeLoop(ILoop loop, IToken token) throws WorkflowException {
        
        boolean oldAlive = token.isAlive();

        EdgeEvent e = new EdgeEvent(loop);
        e.setToken(token);
        e.setEventType(EdgeEvent.ON_TAKING_THE_TOKEN);

        for (int i = 0; loop.getEventListeners() != null && i < loop.getEventListeners().size(); i++) {
            IEdgeEventListener listener =  loop.getEventListeners().get(i);
            listener.onEdgeEventFired(e);
        }

        boolean newAlive = token.isAlive();

        if (!newAlive){//循环条件不满足，则恢复token的alive标示
            token.setAlive(oldAlive);
            return newAlive;
        } else {
            //否则流转到下一个节点
            INode node = loop.getLeavingNode();
            token.setValue(loop.getWeight());
            //触发同步器节点
            fireNode(node, token);
            return newAlive;
        }        
    }
    /**
     * 接受一个token，并移交给下一个节点
     * 
     * @param token
     * @return 返回值是该transition计算出的token的alive值
     * @throws org.fireflow.kenel.KenelException
     */
    private boolean takeTransition(ITransition transition, IToken token) throws WorkflowException {
        
        EdgeEvent e = new EdgeEvent(transition);
        e.setToken(token);
        e.setEventType(EdgeEvent.ON_TAKING_THE_TOKEN);
    
        for (int i = 0; transition.getEventListeners() != null && i < transition.getEventListeners().size(); i++) {
            IEdgeEventListener listener =  transition.getEventListeners().get(i);
            listener.onEdgeEventFired(e); //调用TransitionInstanceExtension 来计算弧线上的条件表达式
        }
    
        INode nodeInst = transition.getLeavingNode(); //获取到流向哪个节点
        token.setValue(transition.getWeight());//获取到弧线上的权值
        
        boolean alive = token.isAlive();
    
        fireNode(nodeInst, token); //节点触发
    
        return alive;        
    }
    
    public void archiveTaskInstances(IActivity activityInstance) {
        // TODO Auto-generated method stub
    	// not implement yet
    }

    public final void createTaskInstances(IToken token, IActivity activityInstance) throws WorkflowException {
        
        WFActivity activity = activityInstance.getNodeModel();
        IWorkflowDAO persistenceService = context.getPersistenceService();
        ICalendarService calService = context.getCalendarService();

        IProcessInstance processInstance = token.getProcess();

        int createdTaskInstanceCount = 0;
        for (int i = 0; i < activity.getTasks().size(); i++) {
            WFTask task = activity.getTasks().get(i);
            // 1、创建Task实例，并设置工作流系统定义的属性
            ITaskInstance taskInstance = createTaskInstance(processInstance, task, activity);

            if (taskInstance == null) {
                continue;
            }
            createdTaskInstanceCount = createdTaskInstanceCount + 1;
            
            ((TaskInstance) taskInstance).setStepNum(token.getStepNumber());
            ((TaskInstance) taskInstance).setFromActivityId(token.getFromActivityId());

            // 计算超时
            Duration duration = task.getDuration();

            if (duration != null && calService != null) {
                ((TaskInstance) taskInstance).setExpiredTime(new Date(calService.dateAfter(calService.getSysDate(), duration).getTime()));
            }

            // 2、保存实例taskInstance
            persistenceService.saveOrUpdateTask((TaskInstance)taskInstance);

            // 3、启动实例
            startTaskInstance(taskInstance);

        }
        
        if (createdTaskInstanceCount == 0) { //如果是空activity，哪么直接结束
            complete(activityInstance, null, token);
        }
    }

    /* (non-Javadoc)
     * @see org.fireflow.engine.ITaskInstance#suspend()
     */
    public void suspend(ITaskInstance task) throws WorkflowException {
        if (task.getState() == ITaskInstance.COMPLETED || task.getState() == ITaskInstance.CANCELED) {
            throw new WorkflowException(task.getProcess(), task.getTaskModel(), "The task instance can not be suspended,the state of this task instance is " + task.getState());
        }
        if (task.isSuspended()) {
            return;
        }
        ((TaskInstance)task).setSuspended(Boolean.TRUE);
        IWorkflowDAO persistenceService = context.getPersistenceService();
        persistenceService.saveOrUpdateTask(task);
    }

    /* (non-Javadoc)
     * @see org.fireflow.engine.ITaskInstance#restore()
     */
    public void restore(ITaskInstance task) throws WorkflowException {
        if (task.getState() == ITaskInstance.COMPLETED || task.getState() == ITaskInstance.CANCELED) {
            throw new WorkflowException(task.getProcess(), task.getTaskModel(), "The task instance can not be restored,the state of this task instance is " + task.getState());
        }
        if (!task.isSuspended()) {
            return;
        }
        ((TaskInstance)task).setSuspended(Boolean.FALSE);
        IWorkflowDAO persistenceService = context.getPersistenceService();
        persistenceService.saveOrUpdateTask(task);
    }

    /* (non-Javadoc)
     * @see org.fireflow.engine.ITaskInstance#abort()
     */
    public void abort(ITaskInstance task) throws WorkflowException {
        abort(task, null);
    }

    /* (non-Javadoc)
     * @see org.fireflow.engine.ITaskInstance#abort(java.lang.String)
     */
    public void abort(ITaskInstance task, String targetActivityId) throws WorkflowException {
        abort(task, targetActivityId, null);

    }

    /* (non-Javadoc)
     * @see org.fireflow.engine.ITaskInstance#abortEx(java.lang.String, org.fireflow.engine.taskinstance.DynamicAssignmentHandler)
     */
    public void abort(ITaskInstance task, String targetActivityId, DefaultDynamicTaskAssignor dynamicAssignmentHandler) throws WorkflowException {

        if ((task.getState().intValue() == ITaskInstance.COMPLETED)
                || (task.getState().intValue() == ITaskInstance.CANCELED)) {
            throw new WorkflowException(task.getProcess().getId(), task.getProcess().getModel(),
                task.getTaskModelId(), 
                "Abort task instance failed . The state of the task instance [id=" + task.getId() + "] is " + task.getState());
        }
//
//        if (dynamicAssignmentHandler != null) {
//            setDynamicAssignmentHandler(dynamicAssignmentHandler);
//        }
        abortTaskInstanceEx(task, targetActivityId);
    }

    /**
     * 
     * @param currentSession
     * @param processInstance
     * @param task
     * @param activity
     * @return
     * @throws WorkflowException
     */
    public ITaskInstance createTaskInstance(IProcessInstance processInstance, WFTask wftask, WFActivity wfactivity)
            throws WorkflowException {
        // 如果loopStrategy为SKIP且Task被执行过，则直接返回null;
        IWorkflowDAO persistenceService = this.context.getPersistenceService();
        String loopStrategy = wftask.getLoopStrategy();
        if (loopStrategy != null 
                && WFTask.SKIP.equals(loopStrategy) 
                && !isInWithdrawOrRejectOperation()) {
            // 检查是否已经执行过的task instance
            Integer count = persistenceService.countCompletedTaskForTaskModel(
                processInstance.getId(), wftask.getId());
            if (count > 0) {
                return null;
            }
        }
        return new TaskInstance(processInstance, wftask, wfactivity);
    }

    /**
     * 启动TaskInstance。<br>
     * 该方法定义为final,不允许子类扩展。
     * 
     * @param task
     * @throws org.WorkflowException.engine.EngineException
     * @throws org.fireflow.kenel.KenelException
     */
    protected final void startTaskInstance(ITaskInstance task) throws WorkflowException {

        WFTask wf_task = task.getTaskModel();

        String taskType = wf_task.getType();

        String taskRunnerName = wf_task.getTaskRunner();
        if (StringUtils.isEmpty(taskRunnerName)) {
            if (WFTask.FORM.equals(taskType)) {
                taskRunnerName = task.getProcess().getModel()
                        .getFormTaskRunnerName();
            } else if (WFTask.AUTO.equals(taskType)) {
                taskRunnerName = task.getProcess().getModel()
                        .getToolTaskRunnerName();
            } else if (WFTask.SUBFLOW.equals(taskType)) {
                taskRunnerName = task.getProcess().getModel()
                        .getSubflowTaskRunnerName();
            }
        }
        
        ITaskHandler taskInstanceRunner = null;
        if (StringUtils.isNotEmpty(taskRunnerName)) {
            try {
                taskInstanceRunner = (ITaskHandler) Class.forName(taskRunnerName).newInstance();
            } catch (Exception e1) {
                logger.error("Create task runner ["+taskRunnerName+"] error!", e1);
                taskInstanceRunner = null;
            }
        } else {
            if (WFTask.FORM.equals(taskType)) {
                taskInstanceRunner = formTaskRunner;
            } else if (WFTask.AUTO.equals(taskType)) {
                taskInstanceRunner = toolTaskRunner;
            } else if (WFTask.SUBFLOW.equals(taskType)) {
                taskInstanceRunner = subflowTaskRunner;
            }
        }
        
        if (taskInstanceRunner== null) {
            WFProcess wf_process = task.getProcess().getModel();
            throw new WorkflowException(task.getProcess().getId(),
                    wf_process, task.getTaskModelId(),
                    "无法获取任务运行器—TaskInstanceRunner,TaskId=" + wf_task.getId()
                            + ", taskType=" + task.getTaskType());            
        }
        
        //开始运行任务 dzb
        // 触发事件
        TaskEvent e = new TaskEvent();
        e.setSource(task);
        e.setEventType(TaskEvent.BEFORE_TASK_INSTANCE_START);
        
        //FIXME:
//        if (taskEventListener != null) {
//            taskEventListener.onTaskEventFired(e);
//        }
        
        this.fireTaskInstanceEvent(task, e);

        ((TaskInstance) task).setState(ITaskInstance.RUNNING);
        ((TaskInstance) task).setStartedTime(new Date(System.currentTimeMillis()));
        this.context.getPersistenceService().saveOrUpdateTask((TaskInstance)task);
        
        taskInstanceRunner.handle(this, task);
    }

    /**
     * 判断TaskInstance是否可以结束，缺省的判断规则是：没有活动的WorkItem即可结束。<br>
     * 业务代码可以重载该函数，对特定的Task采取特殊的判断规则。
     * 
     * @param taskInstance
     * @return
     */
    protected final boolean taskInstanceCanBeCompleted(ITaskInstance taskInstance) throws WorkflowException {

        WFTask task = taskInstance.getTaskModel();
        String taskInstanceCompletionEvaluatorName = null;
        ITaskEvaluator taskInstanceCompletionEvaluator = null;

        String taskType = task.getType();

        taskInstanceCompletionEvaluatorName = task.getTaskCompletionEvaluator();
        if (taskInstanceCompletionEvaluatorName != null
                && !taskInstanceCompletionEvaluatorName.trim().equals("")) {
            
            //TODO dzb... ioc 
            
//          IBeanFactory beanFactory = runtimeContext.getBeanFactory();
//          taskInstanceCompletionEvaluator = (ITaskInstanceCompletionEvaluator) beanFactory
//                  .getBean(taskInstanceCompletionEvaluatorName);
        }
        
        IProcessInstance processInstance = taskInstance.getProcess();
        
        if (taskInstanceCompletionEvaluator == null) {
            if (WFTask.FORM.equals(taskType)) {
                taskInstanceCompletionEvaluatorName = processInstance
                        .getModel()
                        .getFormTaskCompletionEvaluatorName();
            } else if (WFTask.AUTO.equals(taskType)) {
                taskInstanceCompletionEvaluatorName = processInstance
                        .getModel()
                        .getToolTaskCompletionEvaluatorName();
            } else if (WFTask.SUBFLOW.equals(taskType)) {
                taskInstanceCompletionEvaluatorName = processInstance
                        .getModel()
                        .getSubflowTaskCompletionEvaluatorName();
            }
            if (taskInstanceCompletionEvaluatorName != null
                    && !taskInstanceCompletionEvaluatorName.trim().equals("")) {
                //TODO ioc
//              IBeanFactory beanFactory = runtimeContext.getBeanFactory();
//              taskInstanceCompletionEvaluator = (ITaskInstanceCompletionEvaluator) beanFactory
//                      .getBean(taskInstanceCompletionEvaluatorName);
            }
        }

        if (taskInstanceCompletionEvaluator == null) {
            if (WFTask.FORM.equals(taskType)) {
                taskInstanceCompletionEvaluator = this.formTaskEvaluator;
            } else if (WFTask.AUTO.equals(taskType)) {
                taskInstanceCompletionEvaluator = this.toolTaskEvaluator;
            } else if (WFTask.SUBFLOW.equals(taskType)) {
                taskInstanceCompletionEvaluator = this.subflowTaskEvaluator;
            }
        }
        if (taskInstanceCompletionEvaluator != null) {
            return taskInstanceCompletionEvaluator.eval(this, taskInstance);
        } else {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(),
                    "无法获取TaskInstanceCompletionEvaluator,TaskId="
                            + task.getId() + ", taskType="
                            + taskInstance.getTaskType());
        }
    }

    /**
     * 
     * @param taskInstance
     * @return
     * @throws WorkflowException
     */
    protected boolean activityInstanceCanBeCompleted(ITaskInstance taskInstance)
            throws WorkflowException {
        IWorkflowDAO persistenceService = this.context
                .getPersistenceService();
        WFActivity thisActivity = (WFActivity) taskInstance.getActivityModel();
        // 检查是否有尚未创建的TaskInstance
        if (thisActivity.getTasks().size() > 1) {
            List<ITaskInstance> taskInstanceList = persistenceService.findTasks(taskInstance.getProcess().getId(), taskInstance.getStepNum());
            if (taskInstanceList == null
                    || taskInstanceList.size() < thisActivity.getTasks().size()) {
                return false;
            }
        }
        if (thisActivity.getCompletionStrategy().equals(WFActivity.ALL)) {
            Integer aliveTaskInstanceCount4ThisActivity = persistenceService
                    .countAliveTaskForActivityModel(taskInstance.getProcess().getId(), taskInstance
                            .getActivityModelId());

            if (aliveTaskInstanceCount4ThisActivity.intValue() > 0) {
                return false;// 尚有未结束的TaskInstance
            } else {
                return true;
            }
        } else {
            return true;// 此处应该不需要判断，因为对于已经结束的Activity已经没有对应的token。所以继续往下执行不会导致逻辑错误。
        }
    }

    /**
     * 终止当前TaskInstance，检查是否可以中止当前ActivityInstance，如果可以，
     * 则结束当前ActivityInstance，并触发targetActivityInstance或后继ActivityInstance
     * 
     * @param taskInstance
     * @param targetActivityInstance
     * @throws org.WorkflowException.engine.EngineException
     */
    public final void completeTaskInstance(ITaskInstance taskInstance, IActivity targetActivityInstance) throws WorkflowException {
        // 如果TaskInstance处于结束状态，则直接返回
        if (taskInstance.getState() == ITaskInstance.COMPLETED
                || taskInstance.getState() == ITaskInstance.CANCELED) {
            return;
        }
        if (taskInstance.getState() == ITaskInstance.INITIALIZED) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(),
                    "Complete task insatance failed.The state of the task insatnce[id="
                            + taskInstance.getId() + "] is "
                            + taskInstance.getState());
        }
        if (taskInstance.isSuspended()) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(),
                    "Complete task insatance failed. The task instance [id="
                            + taskInstance.getId() + "] is suspended");
        }

        if (targetActivityInstance != null) {
            ((TaskInstance) taskInstance).setTargetActivityId(targetActivityInstance.getNodeId());
        }

        IWorkflowDAO persistenceService = this.context
                .getPersistenceService();

        // 第一步，首先结束当前taskInstance
        if (!taskInstanceCanBeCompleted(taskInstance)) {
            return;
        }
        ((TaskInstance) taskInstance).setState(ITaskInstance.COMPLETED);
        ((TaskInstance) taskInstance).setCanBeWithdrawn(Boolean.FALSE);
        ((TaskInstance) taskInstance).setEndTime(new Date(System.currentTimeMillis()));
        persistenceService.saveOrUpdateTask(taskInstance);
        // 触发相应的事件
        TaskEvent e = new TaskEvent();

        e.setSource(taskInstance);
        e.setEventType(TaskEvent.AFTER_TASK_INSTANCE_COMPLETE);
        
//		FIXME
//        if (this.taskEventListener != null) {
//            this.taskEventListener.onTaskEventFired(e);
//        }

        this.fireTaskInstanceEvent(taskInstance, e);

        // 第二步，检查ActivityInstance是否可以结束
        if (!activityInstanceCanBeCompleted(taskInstance)) {
            return;
        }

        // 第三步，尝试结束对应的activityInstance
        List<IToken> tokens = persistenceService.findTokens(
                taskInstance.getProcess().getId(), taskInstance
                        .getActivityModelId());
        // System.out.println("Inside TaskInstance.complete(targetActivityInstance):: tokens.size is "+tokens.size());
        if (tokens == null || tokens.size() == 0) {
            return;// 表明activityInstance已经结束了。
        }
        if (tokens.size() > 1) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(), "与activityId="
                            + taskInstance.getActivityModelId() + "对应的token数量(="
                            + tokens.size() + ")不正确，正确只能为1，因此无法完成complete操作");
        }
        IToken token = tokens.get(0);
        // stepNumber不相等，不允许执行结束操作。
        if (token.getStepNumber().intValue() != taskInstance.getStepNum()
                .intValue()) {
            return;
        }
        if (token.isAlive() == false) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(), "与activityId="
                            + taskInstance.getActivityModelId()
                            + "对应的token.alive=false，因此无法完成complete操作");
        }

        NodeNet net = getNetInstance(taskInstance.getProcess().getModel(), taskInstance.getProcess().getVersion());
        IActivity activity = net.getNode(taskInstance.getActivityModelId());
        if (activity == null) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(), "系统没有找到与activityId="
                            + taskInstance.getActivityModelId()
                            + "对应activityInstance，无法执行complete操作。");
        }

        token.setProcess(taskInstance.getProcess());
        
        complete(activity, targetActivityInstance, token);
    }

    /**
     * 中止当前的TaskInstance,并使得流程流转到指定的环节。
     * 
     * @param currentSession
     * @param processInstance
     * @param taskInstance
     * @param targetActivityInstance
     * @throws WorkflowException
     */
    public final void abortTaskInstance(ITaskInstance taskInstance, String targetActivityId) throws WorkflowException {
        // 如果TaskInstance处于结束状态，则直接返回
        if (taskInstance.getState() == ITaskInstance.COMPLETED
                || taskInstance.getState() == ITaskInstance.CANCELED) {
            return;
        }
        // Initialized状态的TaskInstance也可以中止，20090830
        // if (taskInstance.getAliveState() == ITaskInstance.INITIALIZED) {
        // WorkflowProcess process = taskInstance.getWorkflowProcess();
        // throw new EngineException(taskInstance.getProcessInstanceId(),
        // process,
        // taskInstance.getTaskId(),
        // "Complete task insatance failed.The state of the task insatnce[id=" +
        // taskInstance.getId() + "] is " + taskInstance.getAliveState());
        // }
        if (taskInstance.isSuspended()) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(),
                    "Abort task insatance failed. The task instance [id="
                            + taskInstance.getId() + "] is suspended");
        }

        // 1）检查是否在同一个“执行线”上

        WFProcess workflowProcess = taskInstance.getProcess().getModel();
        if (targetActivityId != null) {
            String thisActivityId = taskInstance.getActivityModelId();
            boolean isInSameLine = workflowProcess.isInSameLine(thisActivityId,
                    targetActivityId);
            if (!isInSameLine) {
                throw new WorkflowException(
                        taskInstance.getProcess().getId(),
                        taskInstance.getProcess().getModel(),
                        taskInstance.getTaskModelId(),
                        "Jumpto refused because of the current activitgy and the target activity are NOT in the same 'Execution Thread'.");
            }
        }

        NodeNet net = getNetInstance(workflowProcess, taskInstance.getProcess().getVersion());
        IActivity targetActivityInstance = net.getNode(targetActivityId);

        IActivity thisActivityInstance = net.getNode(taskInstance.getActivityModelId());
        if (thisActivityInstance == null) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(), "系统没有找到与activityId="
                            + taskInstance.getActivityModelId() 
                            + "对应activityInstance，无法执行abort操作。");
        }

        if (targetActivityInstance != null) {
            ((TaskInstance) taskInstance)
                    .setTargetActivityId(targetActivityInstance.getNodeModel().getId());
        }

        IWorkflowDAO persistenceService = this.context
                .getPersistenceService();

        // 第一步，首先Abort当前taskInstance
        persistenceService.abortTask((TaskInstance) taskInstance);

        // 触发相应的事件
        TaskEvent e = new TaskEvent();
        e.setSource(taskInstance);
        e.setEventType(TaskEvent.AFTER_TASK_INSTANCE_COMPLETE);
        
        //FIXME        
//        if (this.taskEventListener != null) {
//            this.taskEventListener.onTaskEventFired(e);
//        }

        this.fireTaskInstanceEvent(taskInstance, e);

        // 第二步，检查ActivityInstance是否可以结束
        if (!activityInstanceCanBeCompleted(taskInstance)) {
            return;
        }

        // 第三步，尝试结束对应的activityInstance
        List<IToken> tokens = persistenceService.findTokens(
                taskInstance.getProcess().getId(), taskInstance
                        .getActivityModelId());
        // System.out.println("Inside TaskInstance.complete(targetActivityInstance):: tokens.size is "+tokens.size());
        if (tokens == null || tokens.size() == 0) {
            return;// 表明activityInstance已经结束了。
        }
        if (tokens.size() > 1) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(), "与activityId="
                            + taskInstance.getActivityModelId() + "对应的token数量(="
                            + tokens.size() + ")不正确，正确只能为1，因此无法完成complete操作");
        }
        IToken token = tokens.get(0);
        // stepNumber不相等，不允许执行结束操作。
        if (token.getStepNumber().intValue() != taskInstance.getStepNum()
                .intValue()) {
            return;
        }
        if (token.isAlive() == false) {
            WFProcess process = taskInstance.getProcess().getModel();
            throw new WorkflowException(taskInstance.getProcess().getId(),
                    process, taskInstance.getTaskModelId(), "与activityId="
                            + taskInstance.getActivityModelId()
                            + "对应的token.alive=false，因此无法完成complete操作");
        }

        token.setProcess(taskInstance.getProcess());

        complete(thisActivityInstance, targetActivityInstance, token);
    }

    /**
     * 中止task instance。
     * @param currentSession
     * @param processInstance
     * @param taskInstance
     * @param targetActivityInstance
     * @throws WorkflowException
     */
    public final void abortTaskInstanceEx(ITaskInstance thisTaskInst, String targetActivityId) throws WorkflowException {
        // 如果TaskInstance处于结束状态，则直接返回
        if (thisTaskInst.getState() == ITaskInstance.COMPLETED || thisTaskInst.getState() == ITaskInstance.CANCELED) {
            return;
        }
        
        // Initialized状态的TaskInstance也可以中止，20090830
        // if (taskInstance.getAliveState() == ITaskInstance.INITIALIZED) {
        // WorkflowProcess process = taskInstance.getWorkflowProcess();
        // throw new EngineException(taskInstance.getProcessInstanceId(),
        // process,
        // taskInstance.getTaskId(),
        // "Complete task insatance failed.The state of the task insatnce[id=" +
        // taskInstance.getId() + "] is " + taskInstance.getAliveState());
        // }
        if (thisTaskInst.isSuspended()) {
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    thisTaskInst.getProcess().getModel(), 
                    thisTaskInst.getTaskModelId(),
                    "Abort task insatance failed. The task instance [id="
                            + thisTaskInst.getId() + "] is suspended");
        }
        
        WFProcess wf_process = thisTaskInst.getProcess().getModel();
        // 
        IWorkflowDAO persistenceService = this.context.getPersistenceService();

        List<IToken> allTokens = null;
        List<String> aliveActivityIdsAfterJump = new ArrayList<String>();
        if (targetActivityId != null) {         
            String thisActivityId = thisTaskInst.getActivityModelId();
            boolean isInSameLine = wf_process.isInSameLine(thisActivityId,
                    targetActivityId);
            
            if (isInSameLine){
                abortTaskInstance(thisTaskInst, targetActivityId);
            }
            
            //合法性检查
            allTokens = persistenceService.findTokens(thisTaskInst.getProcess().getId(), null);

            aliveActivityIdsAfterJump.add(targetActivityId);
            
            for (int i=0;allTokens!=null && i<allTokens.size();i++){
                IToken tokenTmp = allTokens.get(i);
                WFElement workflowElement = wf_process.findWFElementById(tokenTmp.getNodeId());
                if ((workflowElement instanceof WFActivity) && !workflowElement.getId().equals(thisActivityId)){
                    
                    aliveActivityIdsAfterJump.add(workflowElement.getId());
                    
                    if (wf_process.isReachable(targetActivityId, workflowElement.getId()) 
                        || wf_process.isReachable(workflowElement.getId(), targetActivityId)){
                        throw new WorkflowException(thisTaskInst.getProcess().getId(),
                            wf_process, 
                            thisTaskInst.getTaskModelId(),
                            "Abort refused because of the business-logic conflict!");

                    }
                }
            }            
        }

        NodeNet net = getNetInstance(wf_process, thisTaskInst.getProcess().getVersion());
        
        IActivity targetActivityInstance = null;
        
        if (targetActivityId!=null){
            targetActivityInstance = net.getNode(targetActivityId);
        }

        IActivity thisActivityInstance = net.getNode(thisTaskInst.getActivityModelId());
        if (thisActivityInstance == null) {          
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                wf_process, thisTaskInst.getTaskModelId(), "系统没有找到与activityId="
                            + thisTaskInst.getActivityModelId() 
                            + "对应activityInstance，无法执行abort操作。");
        }

        if (targetActivityInstance != null) {
            ((TaskInstance) thisTaskInst)
                    .setTargetActivityId(targetActivityInstance.getNodeId());
        }


        // 第一步，首先Abort当前taskInstance
        persistenceService.abortTask((TaskInstance) thisTaskInst);

        // 触发相应的事件
        TaskEvent e = new TaskEvent();
        e.setSource(thisTaskInst);
        e.setEventType(TaskEvent.AFTER_TASK_INSTANCE_COMPLETE);
        
        //FIXME
//        if (this.taskEventListener != null) {
//            this.taskEventListener.onTaskEventFired(e);
//        }

        this.fireTaskInstanceEvent(thisTaskInst, e);

        // 第二步，检查ActivityInstance是否可以结束
        if (!activityInstanceCanBeCompleted(thisTaskInst)) {
            return;
        }

        // 第三步，尝试结束对应的activityInstance
        List<IToken> tokens = persistenceService.findTokens(
                thisTaskInst.getProcess().getId(), thisTaskInst
                        .getActivityModelId());
        // System.out.println("Inside TaskInstance.complete(targetActivityInstance):: tokens.size is "+tokens.size());
        if (tokens == null || tokens.size() == 0) {
            return;// 表明activityInstance已经结束了。
        }
        if (tokens.size() > 1) {
            WFProcess process = thisTaskInst.getProcess().getModel();
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    process, thisTaskInst.getTaskModelId(), "与activityId="
                            + thisTaskInst.getActivityModelId() + "对应的token数量(="
                            + tokens.size() + ")不正确，正确只能为1，因此无法完成complete操作");
        }
        IToken token = tokens.get(0);
        // stepNumber不相等，不允许执行结束操作。
        if (token.getStepNumber().intValue() != thisTaskInst.getStepNum()
                .intValue()) {
            return;
        }
        if (token.isAlive() == false) {
            WFProcess process = thisTaskInst.getProcess().getModel();
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    process, thisTaskInst.getTaskModelId(), "与activityId="
                            + thisTaskInst.getActivityModelId()
                            + "对应的token.alive=false，因此无法完成complete操作");
        }

        token.setProcess(thisTaskInst.getProcess());

        //调整token布局
        if (targetActivityId != null) {
            List<WFSyncRouter> allSynchronizersAndEnds = new ArrayList<WFSyncRouter>(); 
            allSynchronizersAndEnds.addAll(wf_process.getSynchronizers());
            allSynchronizersAndEnds.addAll(wf_process.getEndNodes());
            for (int i=0;i<allSynchronizersAndEnds.size();i++){
                WFSyncRouter synchronizer = allSynchronizersAndEnds.get(i);
                if (synchronizer.getName().equals("Synchronizer4")){
                    System.out.println(synchronizer.getName());
                }
                int volumn = 0;
                if (synchronizer instanceof WFEndNode){
                    volumn = synchronizer.getEnteringTransitions().size();
                }else{
                    volumn = synchronizer.getEnteringTransitions().size()*synchronizer.getLeavingTransitions().size();
                }           
                IToken tokenTmp =  new Token();
                tokenTmp.setNodeId(synchronizer.getId());
                tokenTmp.setAlive(false);
                tokenTmp.setProcess(thisTaskInst.getProcess());
                tokenTmp.setStepNumber(-1);

                List<String> incomingTransitionIds = new ArrayList<String>();
                boolean reachable = false;
                List<WFTransition> enteringTrans = synchronizer.getEnteringTransitions();           
                for (int m=0;m<aliveActivityIdsAfterJump.size();m++){
                    String aliveActivityId = aliveActivityIdsAfterJump.get(m);
                    if (wf_process.isReachable(aliveActivityId, synchronizer.getId())){                    
                        WFTransition trans = null;
                        reachable = true;
                        for (int j=0;j<enteringTrans.size();j++){
                            trans = enteringTrans.get(j);
                            WFNode fromNode = (WFNode)trans.getFromNode();
                            if (wf_process.isReachable(aliveActivityId, fromNode.getId())){
                                if (!incomingTransitionIds.contains(trans.getId())){
                                    incomingTransitionIds.add(trans.getId());
                                }
                            }
                        }           
                    }
                }
                if (reachable){
                    tokenTmp.setValue(volumn-(incomingTransitionIds.size()*volumn/enteringTrans.size()));   
                    
                    IToken virtualToken = getJoinInfo(allTokens,synchronizer.getId());
                    
                    if (virtualToken!=null){
                        persistenceService.deleteTokens(thisTaskInst.getProcess().getId(), synchronizer.getId());
                    }
                    
                    if (tokenTmp.getValue()!=0){
                        tokenTmp.setProcess(thisTaskInst.getProcess());
                        persistenceService.saveOrUpdateToken(tokenTmp);
                    }
                }
            }
        }
        // 结束本节点
        complete(thisActivityInstance, targetActivityInstance, token);
    }
    
    /**
     * 触发task instance相关的事件
     * 
     * @param event
     * @throws org.WorkflowException.engine.EngineException
     */
    protected final void fireTaskInstanceEvent(ITaskInstance taskInstance, 
    		TaskEvent event) throws WorkflowException {
        
    	WFTask taskModel = taskInstance.getTaskModel();
        
        if (taskModel == null) {
            return;
        }

        List<WFEventListener> listeners = taskModel.getEventListeners();
        for (int i = 0; i < listeners.size(); i++) {
            WFEventListener listener = listeners.get(i);
            Object obj = null;
			try {
				//FIXME: 是否统一使用监听器管理器？
				obj = Class.forName(listener.getClassName()).newInstance();
			} catch (Exception e) {
				e.printStackTrace();
			}
            if (obj != null && (obj instanceof ITaskEventListener)) {
                ((ITaskEventListener) obj).onTaskEventFired(this, event);
            }
        }
    }

    /**
     * 根据TaskInstance创建workItem。
     * @param taskInstance
     * @param actorId
     * @return
     * @throws org.WorkflowException.engine.EngineException
     */
    public final WorkItem createWorkItem(ITaskInstance taskInstance, String actorId) throws WorkflowException {
    	
        IWorkflowDAO persistence = context.getPersistenceService();

        WorkItem wi = new WorkItem();
        wi.setTask(taskInstance);
        wi.setActorId(actorId);
        wi.setState(IWorkItem.INITIALIZED);
        wi.setCreatedTime(context.getCalendarService().getSysDate());
        // 保存到数据库
        persistence.saveOrUpdateWorkItem(wi);

        // 触发相应的事件
        TaskEvent event = new TaskEvent();
        event.setSource(taskInstance);
        event.setWorkItem(wi);
        event.setEventType(TaskEvent.AFTER_WORKITEM_CREATED);
        
        //FIXME: 是否要有引擎级别的TaskEventListener        
//        if (this.taskEventListener != null) {
//            this.taskEventListener.onTaskEventFired(this, e);
//        }
        
        this.fireTaskInstanceEvent(taskInstance, event);

        return wi;
    }


    /**
     * 签收WorkItem。
     * @param workItem
     * @throws org.WorkflowException.engine.EngineException
     * @throws org.fireflow.kenel.KenelException
     */
    public final IWorkItem claimWorkItem(String workItemId, String taskInstanceId) throws WorkflowException {
        
        IWorkflowDAO persistenceService = context.getPersistenceService();

        persistenceService.lockTask(taskInstanceId);

        IWorkItem workItem = persistenceService.findWorkItem(workItemId);

        if (workItem == null)
            return null;

        if (workItem.getState().intValue() != IWorkItem.INITIALIZED) {
            TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    thisTaskInst.getProcess().getModel(),
                    thisTaskInst.getTaskModelId(),
                    "Claim work item failed. The state of the work item is "
                            + workItem.getState());
        }
        if (workItem.getTask().getState().intValue() != ITaskInstance.INITIALIZED
                && workItem.getTask().getState().intValue() != ITaskInstance.RUNNING) {
            TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    thisTaskInst.getProcess().getModel(),
                    thisTaskInst.getTaskModelId(),
                    "Claim work item failed .The state of the correspond task instance is "
                            + workItem.getTask().getState());
        }

        if (workItem.getTask().isSuspended()) {
            TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    thisTaskInst.getProcess().getModel(),
                    thisTaskInst.getTaskModelId(),
                    "Claim work item failed .The  correspond task instance is suspended");
        }

        // 0、首先修改workitem的状态
        ((WorkItem) workItem).setState(IWorkItem.RUNNING);
        ((WorkItem) workItem).setClaimedTime(context.getCalendarService()
                .getSysDate());
        persistenceService.saveOrUpdateWorkItem(workItem);

        // 1、如果不是会签，则删除其他的workitem
        if (WFFormTask.ANY.equals(workItem.getTask().getAssignStrategy())) {
            persistenceService.deleteInitializedWorkItems(workItem.getTask().getId());
        }

        // 2、将TaskInstance的canBeWithdrawn字段改称false。即不允许被撤销
        TaskInstance taskInstance = (TaskInstance) workItem.getTask();
        taskInstance.setCanBeWithdrawn(false);
        persistenceService.saveOrUpdateTask(taskInstance);

        return workItem;

    }

    /**
     * 结束WorkItem
     * @param workItem
     * @throws org.WorkflowException.engine.EngineException
     */
    public void completeWorkItem(IWorkItem workItem, IActivity targetActivity, String comments) 
        throws WorkflowException {
        
        if (workItem.getState().intValue() != IWorkItem.RUNNING) {
            TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();
            // System.out.println("WorkItem的当前状态为"+this.getAliveState()+"，不可以执行complete操作。");
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    thisTaskInst.getProcess().getModel(),
                    thisTaskInst.getTaskModelId(),
                    "Complete work item failed . The state of the work item [id="
                            + workItem.getId() + "] is " + workItem.getState());
        }

        if (workItem.getTask().isSuspended()) {
            TaskInstance thisTaskInst = (TaskInstance) workItem
                    .getTask();

            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                thisTaskInst.getProcess().getModel(), 
                thisTaskInst.getTaskModelId(),
                "Complete work item failed. The correspond task instance [id="
                            + thisTaskInst.getId() + "] is suspended");
        }

        IWorkflowDAO persistenceService = context.getPersistenceService();

        ((WorkItem) workItem).setComments(comments);
        ((WorkItem) workItem).setState(IWorkItem.COMPLETED);
        ((WorkItem) workItem).setEndTime(context.getCalendarService()
                .getSysDate());
        persistenceService.saveOrUpdateWorkItem(workItem);

        // 触发AFTER_WORKITEM_COMPLETE事件
        TaskEvent e = new TaskEvent();
        e.setSource(workItem.getTask());
        e.setEventType(TaskEvent.AFTER_WORKITEM_COMPLETE);
        
        //FIXME  dzb
//        if (this.taskEventListener != null) {
//            this.taskEventListener.onTaskEventFired(e);
//        }

        this.fireTaskInstanceEvent(workItem.getTask(), e);

        completeTaskInstance(workItem.getTask(), targetActivity);
    }

    /**
     * 结束工单并跳转
     * @param workItem
     * @param targetActivityId
     * @param nextActorIds
     * @param needClaim
     * @throws org.WorkflowException.engine.EngineException
     */
    public void completeWorkItemAndJumpTo(IWorkItem workItem,
            String targetActivityId, String comments) throws WorkflowException {
        // 首先检查是否可以正确跳转
        // 1）检查是否在同一个“执行线”上
        TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();
        WFProcess workflowProcess = thisTaskInst.getProcess().getModel();
        String thisActivityId = thisTaskInst.getActivityModelId();
        boolean isInSameLine = workflowProcess.isInSameLine(thisActivityId,
                targetActivityId);
        
        if (!isInSameLine) {
            throw new WorkflowException(
                    workflowProcess.getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Jumpto refused because of the current activitgy and the target activity are NOT in the same 'Execution Thread'.");
        }

        // 2）检查目标Activity Form Task的数量(暂时关闭该检查项目)
        // Activity targetActivity =
        // (Activity)workflowProcess.findWFElementById(activityId);
        // int count = getFormTaskCount(targetActivity);
        // if (count!=1){
        // if (!isInSameLine) throw new
        // EngineException("Jumpto refused because of the  FORM-type-task count of the target activitgy  is NOT 1; the count is "+count);
        // }

        // 3)检查当前的 taskinstance是否可以结束
        IWorkflowDAO persistenceService = context.getPersistenceService();

        Integer aliveWorkItemCount = persistenceService
                .countAliveWorkItem(thisTaskInst.getId());
        if (aliveWorkItemCount != null && aliveWorkItemCount > 1) {
            throw new WorkflowException(
                    thisTaskInst.getProcess().getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Jumpto refused because of current taskinstance can NOT be completed. some workitem of this taskinstance is in runing state or initialized state");

        }

        // 4)检查当前的activity instance是否可以结束
        if (WFActivity.ALL.equals(workItem.getTask().getActivityModel()
                .getCompletionStrategy())) {

            Integer aliveTaskInstanceCount4ThisActivity = 
                persistenceService.countAliveTaskForActivityModel(thisTaskInst.getProcess().getId(), thisTaskInst.getActivityModelId());
            
            // 大于2表明当前Activity不可以complete
            if (aliveTaskInstanceCount4ThisActivity.intValue() > 1) {
                throw new WorkflowException(
                        thisTaskInst.getProcess().getId(),
                        workflowProcess,
                        thisTaskInst.getTaskModelId(),
                        "Jumpto refused because of current activity instance can NOT be completed. some task instance of this activity instance is in runing state or initialized state");
            }
        }

        NodeNet net = getNetInstance(workflowProcess, thisTaskInst.getProcess().getVersion());
        if (net == null) {
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Not find the net instance for workflow process [id="
                            + workflowProcess.getId() + ", version="
                            + thisTaskInst.getProcess().getVersion() + "]");
        }
        
        IActivity targetActivityInstance = net.getNode(targetActivityId);

        if (targetActivityInstance == null) {
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Not find the activity instance  for activity[process id="
                            + workflowProcess.getId() + ", version="
                            + thisTaskInst.getProcess().getVersion()
                            + ",activity id=" + targetActivityId + "]");
        }

        if (context.isEnableTrace()) {

            ProcessTrace trace = new ProcessTrace();
            trace.setProcessInstanceId(thisTaskInst.getProcess().getId());
            trace.setStepNum(workItem.getTask().getStepNum() + 1);
            trace.setType(IProcessTrace.JUMPTO_TYPE);
            trace.setFromNodeId(workItem.getTask().getActivityModelId());
            trace.setToNodeId(targetActivityId);
            trace.setEdgeId("");
            context.getPersistenceService().saveOrUpdateProcessTrace(
                    trace);
        }

        this.completeWorkItem(workItem, targetActivityInstance, comments);
    }

    /**
     * 自由流方法扩展，去除“同一执行线”的限制
     * 结束工单并跳转（超级）
     * @param workItem
     * @param targetActivityId
     * @param comments
     * @throws WorkflowException
     */
    public void completeWorkItemAndJumpToEx(IWorkItem workItem, String targetActivityId, String comments) throws WorkflowException {
        
        // 首先检查是否可以正确跳转 
        TaskInstance thisTaskInst = (TaskInstance) workItem.getTask();
        //找到当前的工作里模型
        WFProcess workflowProcess = thisTaskInst.getProcess().getModel();
        String thisActivityId = thisTaskInst.getActivityModelId();
        
        //如果是在同一条执行线上，那么可以直接跳过去，只是重复判断了是否在同一条执行线上
        boolean isInSameLine = workflowProcess.isInSameLine(thisActivityId,targetActivityId);   
        if (isInSameLine){
            this.completeWorkItemAndJumpTo(workItem, targetActivityId, comments);
            return;
        }
        
        // 2）检查目标Activity Form Task的数量(暂时关闭该检查项目)
        // Activity targetActivity =
        // (Activity)workflowProcess.findWFElementById(activityId);
        // int count = getFormTaskCount(targetActivity);
        // if (count!=1){
        // if (!isInSameLine) throw new
        // EngineException("Jumpto refused because of the  FORM-type-task count of the target activitgy  is NOT 1; the count is "+count);
        // }

        // 3)检查当前的 taskinstance是否可以结束
        IWorkflowDAO persistenceService = context.getPersistenceService();

        Integer aliveWorkItemCount = persistenceService
                .countAliveWorkItem(thisTaskInst.getId());
        if (aliveWorkItemCount != null && aliveWorkItemCount > 1) {
            throw new WorkflowException(
                    thisTaskInst.getProcess().getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Jumpto refused because of current taskinstance can NOT be completed. some workitem of this taskinstance is in runing state or initialized state");

        }

        // 4)检查当前的activity instance是否可以结束
        if (WFActivity.ALL.equals(workItem.getTask().getActivityModel().getCompletionStrategy())) {

            Integer aliveTaskInstanceCount4ThisActivity = persistenceService
                    .countAliveTaskForActivityModel(
                            thisTaskInst.getProcess().getId(), 
                            thisTaskInst.getActivityModelId());
            if (aliveTaskInstanceCount4ThisActivity.intValue() > 1) {// 大于1表明当前Activity不可以complete
                throw new WorkflowException(
                        thisTaskInst.getProcess().getId(),
                        workflowProcess,
                        thisTaskInst.getTaskModelId(),
                        "Jumpto refused because of current activity instance can NOT be completed. some task instance of this activity instance is in runing state or initialized state");
            }
        }
        
        //4)首先检查目标状态M是否存在冲突,如果存在冲突则不允许跳转；如果不存在冲突，则需要调整token
        List<IToken> allTokens = persistenceService.findTokens(thisTaskInst.getProcess().getId(), null);
        List<String> aliveActivityIdsAfterJump = new ArrayList<String>();//计算跳转后，哪些activity节点复活
        aliveActivityIdsAfterJump.add(targetActivityId);
        
        for (int i=0;allTokens!=null && i<allTokens.size();i++){
            IToken tokenTmp = allTokens.get(i);
            WFElement workflowElement = workflowProcess.findWFElementById(tokenTmp.getNodeId()); //找到拥有此token的工作流元素
            if ((workflowElement instanceof WFActivity) && !workflowElement.getId().equals(thisActivityId)){
                //注意：不能自己跳转到自己，同时此工作流元素是activity类型
                aliveActivityIdsAfterJump.add(workflowElement.getId());
                
                if (workflowProcess.isReachable(targetActivityId, workflowElement.getId()) 
                    || workflowProcess.isReachable(workflowElement.getId(), targetActivityId)){
                    throw new WorkflowException(
                            thisTaskInst.getProcess().getId(),
                            workflowProcess,
                            thisTaskInst.getTaskModelId(),
                            "Jumpto refused because of the business-logic conflict!");

                }
            }
        }

        //所有检查结束，开始执行跳转操作
        
        NodeNet net = getNetInstance(workflowProcess, thisTaskInst.getProcess().getVersion());
        if (net == null) {
            throw new WorkflowException(thisTaskInst.getProcess().getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Not find the net instance for workflow process [id="
                            + workflowProcess.getId() + ", version="
                            + thisTaskInst.getProcess().getVersion() + "]");
        }
        
        IActivity targetActivity = net.getNode(targetActivityId);
        
        if (targetActivity == null) {
            throw new WorkflowException(
                    thisTaskInst.getProcess().getId(),
                    workflowProcess,
                    thisTaskInst.getTaskModelId(),
                    "Not find the activity instance  for activity[process id="
                            + workflowProcess.getId() + ", version="
                            + thisTaskInst.getProcess().getVersion()
                            + ",activity id=" + targetActivityId + "]");
        }

        if (context.isEnableTrace()) {

            ProcessTrace trace = new ProcessTrace();
            trace.setProcessInstanceId(thisTaskInst.getProcess().getId());
            trace.setStepNum(workItem.getTask().getStepNum() + 1);
            trace.setType(IProcessTrace.JUMPTO_TYPE);
            trace.setFromNodeId(workItem.getTask().getActivityModelId());
            trace.setToNodeId(targetActivityId);
            trace.setEdgeId("");
            context.getPersistenceService().saveOrUpdateProcessTrace(
                    trace);
        }

        //调整token布局 
        List<WFSyncRouter> allSynchronizersAndEnds = new ArrayList<WFSyncRouter>(); 
        allSynchronizersAndEnds.addAll(workflowProcess.getSynchronizers());
        allSynchronizersAndEnds.addAll(workflowProcess.getEndNodes());
        for (int i=0;i<allSynchronizersAndEnds.size();i++){
            WFSyncRouter synchronizer = allSynchronizersAndEnds.get(i);

            int volumn = 0;
            if (synchronizer instanceof WFEndNode){
                volumn = synchronizer.getEnteringTransitions().size();
            }else{
                volumn = synchronizer.getEnteringTransitions().size()*synchronizer.getLeavingTransitions().size();
            }           
            IToken tokenTmp =  new Token();
            tokenTmp.setNodeId(synchronizer.getId());
            tokenTmp.setAlive(false);
            tokenTmp.setProcess(thisTaskInst.getProcess());
            tokenTmp.setStepNumber(-1);

            List<String> incomingTransitionIds = new ArrayList<String>();
            boolean reachable = false;
            List<WFTransition> enteringTrans = synchronizer.getEnteringTransitions();       
            for (int m=0;m<aliveActivityIdsAfterJump.size();m++){
                String aliveActivityId = aliveActivityIdsAfterJump.get(m);
                if (workflowProcess.isReachable(aliveActivityId, synchronizer.getId())){                    
                    WFTransition trans = null;
                    reachable = true;
                    for (int j=0;j<enteringTrans.size();j++){
                        trans = enteringTrans.get(j);
                        WFNode fromNode = trans.getFromNode();
                        if (workflowProcess.isReachable(aliveActivityId, fromNode.getId())){
                            if (!incomingTransitionIds.contains(trans.getId())){
                                incomingTransitionIds.add(trans.getId());
                            }
                        }
                    }           
                }
            }
            if (reachable){
                tokenTmp.setValue(volumn-(incomingTransitionIds.size()*volumn/enteringTrans.size()));   
                
                IToken virtualToken = getJoinInfo(allTokens,synchronizer.getId()); //获取一个虚拟的综合性token
                
                if (virtualToken!=null){
                    persistenceService.deleteTokens(thisTaskInst.getProcess().getId(), synchronizer.getId());
                }
                
                if (tokenTmp.getValue()!=0){
                    tokenTmp.setProcess(thisTaskInst.getProcess());
                    persistenceService.saveOrUpdateToken(tokenTmp);
                }
            }
        }
        
        this.completeWorkItem(workItem, targetActivity, comments);
    }
    
    /**
     * 获取特定同步器的汇聚信息，如果该同步器已经存在token，则返回一个综合性的虚拟的token，否则返回null。
     * @param allTokens
     * @param routerId
     * @return
     */
    private IToken getJoinInfo(List<IToken> allTokens,String routerId){
        boolean findTokens = false;
        Map<String,IToken> tokensMap = new HashMap<String,IToken>();
        for (int i = 0; i < allTokens.size(); i++) {
            IToken tmpToken = (IToken) allTokens.get(i);
            if (!tmpToken.getNodeId().equals(routerId)){
                continue;
            }
            findTokens = true;
            String tmpFromActivityId = tmpToken.getFromActivityId();
            if (!tokensMap.containsKey(tmpFromActivityId)) {
                tokensMap.put(tmpFromActivityId, tmpToken);
            } else {
                IToken tmpToken2 = (IToken) tokensMap.get(tmpFromActivityId);
                if (tmpToken2.getStepNumber() > tmpToken.getStepNumber()) {
                    tokensMap.put(tmpFromActivityId, tmpToken2);
                }
            }
        }

        if (!findTokens) return null;
        IToken virtualToken = new Token();
        int stepNumber = 0;
        List<IToken> tokensList = new ArrayList<IToken>(tokensMap.values());

        for (int i = 0; i < tokensList.size(); i++) {
            IToken _token = (IToken) tokensList.get(i);
            //Fixed by wmj2003  http://www.fireflow.org/viewthread.php?tid=1040&extra=page%3D1
            virtualToken.setValue(virtualToken.getValue()==null?0:virtualToken.getValue()+_token.getValue());
            if (_token.isAlive()) {
                virtualToken.setAlive(true);
                String oldFromActivityId = virtualToken.getFromActivityId();
                if (oldFromActivityId == null || oldFromActivityId.trim().equals("")) {
                    virtualToken.setFromActivityId(_token.getFromActivityId());
                } else {
                    virtualToken.setFromActivityId(oldFromActivityId + IToken.FROM_ACTIVITY_ID_SEPARATOR + _token.getFromActivityId());
                }
            }
            if (_token.getStepNumber() > stepNumber) {
                stepNumber = _token.getStepNumber();
            }
        }

        virtualToken.setStepNumber(stepNumber + 1);
        
        return virtualToken;
    } 
    

    public void rejectWorkItem(IWorkItem workItem, String comments)
            throws WorkflowException {
        TaskInstance thisTaskInstance = (TaskInstance) workItem.getTask();

        WFActivity thisActivity = thisTaskInstance.getActivityModel();
        if (workItem.getState() > 5 || workItem.getTask().isSuspended()) {// 处于非活动状态,或者被挂起,则不允许reject
            throw new WorkflowException(
                    thisTaskInstance.getProcess().getId(),
                    thisTaskInstance.getProcess().getModel(),
                    thisTaskInstance.getTaskModelId(),
                    "Reject operation refused!Current work item is completed or the correspond task instance is suspended!!");
        }
        // 当前Activity只允许一个Form类型的Task
        if (thisActivity.getTasks().size() > 1) {
            throw new WorkflowException(
                    thisTaskInstance.getProcess().getId(),
                    thisTaskInstance.getProcess().getModel(), 
                    thisTaskInstance.getTaskModelId(),
                    "Reject operation refused!The correspond activity has more than 1 tasks");
        }
        // 汇签Task不允许Reject
        if (WFFormTask.ALL.equals(thisTaskInstance.getAssignStrategy())) {
            throw new WorkflowException(thisTaskInstance.getProcess().getId(),
                    thisTaskInstance.getProcess().getModel(), 
                    thisTaskInstance.getTaskModelId(),
                    "Reject operation refused!The assignment strategy is 'ALL'");
        }
        //----added by wmj2003 20090915 ---start---
        //处理拒收的边界问题
        if(thisTaskInstance.getFromActivityId().equals(IToken.FROM_START_NODE)){
                throw new WorkflowException(
                                thisTaskInstance.getProcess().getId(),
                                thisTaskInstance.getProcess().getModel(),
                                thisTaskInstance.getTaskModelId(),
                                "Reject operation refused!Because the from activityId equals "+IToken.FROM_START_NODE );
        }
        //----added by wmj2003 20090915 ---end---
        IWorkflowDAO persistenceService = this.context.getPersistenceService();
        List<ITaskInstance> siblingTaskInstancesList = null;

        siblingTaskInstancesList = persistenceService
                .findTasks(workItem
                        .getTask().getProcess().getId(),
                        thisTaskInstance.getStepNum());

        // 如果执行了split操作，则不允许reject
        if (siblingTaskInstancesList.size() > 1) {
            throw new WorkflowException(
                    thisTaskInstance.getProcess().getId(),
                    thisTaskInstance.getProcess().getModel(),
                    thisTaskInstance.getTaskModelId(),
                    "Reject operation refused!Because the process instance has taken a split operation.");
        }

        // 检查From Activity中是否有ToolTask和SubflowTask
        List<String> fromActivityIdList = new ArrayList<String>();
        StringTokenizer tokenizer = new StringTokenizer(thisTaskInstance
                .getFromActivityId(), IToken.FROM_ACTIVITY_ID_SEPARATOR);
        while (tokenizer.hasMoreTokens()) {
            fromActivityIdList.add(tokenizer.nextToken());
        }
        WFProcess workflowProcess = thisTaskInstance.getProcess().getModel();
        for (int i = 0; i < fromActivityIdList.size(); i++) {
            String fromActivityId = (String) fromActivityIdList.get(i);
            WFActivity fromActivity = (WFActivity) workflowProcess
                    .findWFElementById(fromActivityId);
            List<WFTask> fromTaskList = fromActivity.getTasks();
            for (int j = 0; j < fromTaskList.size(); j++) {
                WFTask task =  fromTaskList.get(j);
                if (WFTask.AUTO.equals(task.getType())
                        || WFTask.SUBFLOW.equals(task.getType())) {
                    throw new WorkflowException(
                            thisTaskInstance.getProcess().getId(),
                            thisTaskInstance.getProcess().getModel(),
                            thisTaskInstance.getTaskModelId(),
                            "Reject operation refused!The previous activity contains tool-task or subflow-task");

                }
            }
        }
        // 恢复所有的FromTaskInstance
        NodeNet net = getNetInstance(workflowProcess, thisTaskInstance.getProcess().getVersion());
        if (net == null) {
            throw new WorkflowException(
                thisTaskInstance.getProcess().getId(),
                workflowProcess, 
                thisTaskInstance.getTaskModelId(),
                    "Not find the net instance for workflow process [id="
                            + workflowProcess.getId() + ", version="
                            + thisTaskInstance.getProcess().getVersion() + "]");
        }

        // 执行reject操作。         
//      WorkflowEngine session = ((IWorkflowSessionAware) workItem)
//              .getCurrentWorkflowSession();
        setWithdrawOrRejectOperationFlag(true);
        int newStepNumber = thisTaskInstance.getStepNum() + 1;
        try {
            // 首先将本WorkItem和TaskInstance cancel掉。
            workItem.setComments(comments);
            ((WorkItem) workItem).setState(IWorkItem.CANCELED);
            ((WorkItem) workItem).setEndTime(context.getCalendarService()
                    .getSysDate());
            context.getPersistenceService().saveOrUpdateWorkItem(workItem);

            persistenceService.abortTask(thisTaskInstance);

            // 删除本环节的token
            persistenceService.deleteTokens(thisTaskInstance.getProcess().getId(), thisTaskInstance.getActivityModelId());

            IActivity fromActivityInstance = null;
            
            for (String fromActivityId : fromActivityIdList) {
            	
                fromActivityInstance = net.getNode(fromActivityId);;
                
                Token newToken = new Token();
                ((Token) newToken).setAlive(true);
                ((Token) newToken).setNodeId(fromActivityId);
                newToken.setProcess(thisTaskInstance.getProcess());
                newToken.setFromActivityId(thisTaskInstance.getActivityModelId());
                newToken.setStepNumber(newStepNumber);
                newToken.setValue(0);
                persistenceService.saveOrUpdateToken(newToken);

                this.createTaskInstances(newToken, fromActivityInstance);

                if (context.isEnableTrace()) {
                    ProcessTrace trace = new ProcessTrace();
                    trace.setProcessInstanceId(thisTaskInstance.getProcess().getId());
                    trace.setStepNum(newStepNumber);
                    trace.setType(IProcessTrace.REJECT_TYPE);
                    trace.setFromNodeId(thisActivity.getId());
                    trace.setToNodeId(fromActivityId);
                    trace.setEdgeId("");
                    context.getPersistenceService().saveOrUpdateProcessTrace(trace);
                }
            }

            ITransition theLeavingTransitionInstance = (ITransition) fromActivityInstance
                    .getLeavingTransitions().get(0);
            ISyncRouter synchronizerInstance = (ISyncRouter) theLeavingTransitionInstance
                    .getLeavingNode();
            if (synchronizerInstance.getEnteringTransitions().size() > fromActivityIdList
                    .size()) {
                Token supplementToken = new Token();
                ((Token) supplementToken).setAlive(false);
                ((Token) supplementToken).setNodeId(synchronizerInstance.getNodeId());
                supplementToken.setProcess(thisTaskInstance.getProcess());
                supplementToken.setFromActivityId("EMPTY(created by reject)");
                supplementToken.setStepNumber(thisTaskInstance.getStepNum() + 1);
                supplementToken.setValue(synchronizerInstance.getVolume()
                        - theLeavingTransitionInstance.getWeight()
                        * fromActivityIdList.size());
                persistenceService.saveOrUpdateToken(supplementToken);
            }
        } finally {
            setWithdrawOrRejectOperationFlag(false);
        }
    }
    /**
     * 撤销刚才执行的Complete动作，系统将创建并返回一个新的Running状态的WorkItem

     * 对已经结束的工作项执行取回操作<br/>
     * 只有满足如下约束才能正确执行取回操作：<br/>
     * 1) 下一个Activity只有Form类型的Task,没有Tool类型和Subflow类型的Task</br>
     * 2) 下一个环节的所有WorkItem还没有被签收，都处于Initialized状态，<br/>
     * 如果在本WorkItem成功执行了jumpTo操作或者loopTo操作，只要满足上述条件，也可以
     * 成功执行withdraw。<br/>
     * 该方法和IWorkflowSession.withdrawWorkItem(String workItemId)等价。
     * @return 如果取回成功，则创建一个新的WorkItem 并返回该WorkItem
     * @throws org.WorkflowException.engine.EngineException
 
     * @param workItem
     * @return 新创建的工作项
     * @throws org.WorkflowException.engine.EngineException
     */
    public IWorkItem withdrawWorkItem(IWorkItem workItem)
            throws WorkflowException {
        WFActivity thisActivity = workItem.getTask().getActivityModel();
        TaskInstance task = (TaskInstance) workItem
                .getTask();
        if (workItem.getState() < 5) {// 小于5的状态为活动状态
            throw new WorkflowException(task.getProcess().getId(),
                    task.getProcess().getModel(), 
                    task.getTaskModelId(),
                    "Withdraw operation is refused! Current workitem is in running state!!");
        }
        // 当前Activity只允许一个Form类型的Task
        if (thisActivity.getTasks().size() > 1) {
            throw new WorkflowException(task.getProcess().getId(),
                task.getProcess().getModel(), 
                task.getTaskModelId(),
                    "Withdraw operation is refused! The activity[id="
                            + thisActivity.getId() + "] has more than 1 tasks");
        }

        // 汇签Task不允许撤销
        if (WFFormTask.ALL.equals(task.getAssignStrategy())) {
            throw new WorkflowException(task.getProcess().getId(),
                task.getProcess().getModel(), 
                task.getTaskModelId(),
                    "Withdraw operation is refused! The assignment strategy for activity[id="
                            + thisActivity.getId() + "] is 'ALL'");
        }

        IWorkflowDAO persistenceService = this.context.getPersistenceService();
        List<ITaskInstance> targetTaskInstancesList = null;
        targetTaskInstancesList = persistenceService.findTasks(
                        task.getProcess().getId(),
                        task.getStepNum() + 1);

        // 如果targetTaskInstancesList为空或size 等于0,则表示流程实例执行了汇聚操作。
        if (targetTaskInstancesList == null || targetTaskInstancesList.size() == 0) {
            throw new WorkflowException(
                    task.getProcess().getId(),
                    task.getProcess().getModel(),
                    task.getTaskModelId(),
                    "Withdraw operation is refused!Because the process instance has taken a join operation after this activity[id="
                            + thisActivity.getId() + "].");
        } else {
            TaskInstance taskInstance = (TaskInstance) targetTaskInstancesList
                    .get(0);
            if (!taskInstance.getFromActivityId().equals(
                    task.getActivityModelId())) {
                throw new WorkflowException(
                        task.getProcess().getId(),
                        task.getProcess().getModel(),
                        task.getTaskModelId(),
                        "Withdraw operation is refused!Because the process instance has taken a join operation after this activity[id="
                                + thisActivity.getId() + "].");
            }
        }

        for (int i = 0; targetTaskInstancesList != null
                && i < targetTaskInstancesList.size(); i++) {
            TaskInstance targetTaskInstanceTmp = (TaskInstance) targetTaskInstancesList
                    .get(i);
            if (!targetTaskInstanceTmp.getCanBeWithdrawn()) {
                // 说明已经有某些WorkItem处于已签收状态，或者已经处于完毕状态，此时不允许退回
                throw new WorkflowException(
                    task.getProcess().getId(), 
                    task.getProcess().getModel(), 
                    task.getTaskModelId(),
                    "Withdraw operation is refused! Some task instances of the  next activity[id="
                                + targetTaskInstanceTmp.getActivityModelId()
                                + "] are not in 'Initialized' state");
            }
        }

        NodeNet net = getNetInstance(
            task.getProcess().getModel(),
            task.getProcess().getVersion());
        
        if (net == null) {
            throw new WorkflowException(task.getProcess().getId(),
                    task.getProcess().getModel(), 
                    task.getTaskModelId(),
                    "Withdraw operation failed.Not find the net instance for workflow process [id="
                            + task.getProcess().getDefinitionId() + ", version="
                            + task.getProcess().getVersion() + "]");
        }
        
        IActivity thisActivityInstance = net.getNode(task.getActivityModelId());
        
        // 一切检查通过之后进行“收回”处理
        setWithdrawOrRejectOperationFlag(true);
        int newStepNumber = task.getStepNum() + 2;
        try {
            
            List<String> actorIds = new ArrayList<String>();
            actorIds.add(workItem.getActorId());
            
            DefaultDynamicTaskAssignor dynamicAssignmentHandler = new DefaultDynamicTaskAssignor();
            dynamicAssignmentHandler.setActorIdsList(actorIds);        
            
            setDynamicHandler(dynamicAssignmentHandler);

            // 1、首先将后续环节的TaskInstance极其workItem变成Canceled状态
            List<String> targetActivityIdList = new ArrayList<String>();
            StringBuffer theFromActivityIds = new StringBuffer("");
            for (int i = 0; i < targetTaskInstancesList.size(); i++) {
                TaskInstance taskInstTemp = (TaskInstance) targetTaskInstancesList
                        .get(i);

                persistenceService.abortTask(taskInstTemp);

                if (!targetActivityIdList.contains(taskInstTemp.getActivityModelId())) {
                    targetActivityIdList.add(taskInstTemp.getActivityModelId());
                    if (theFromActivityIds.length() == 0) {
                        theFromActivityIds.append(taskInstTemp.getActivityModelId());
                    } else {
                        theFromActivityIds.append(
                                IToken.FROM_ACTIVITY_ID_SEPARATOR).append(
                                taskInstTemp.getActivityModelId());
                    }
                }
            }

            persistenceService.deleteTokens(task.getProcess().getId(), targetActivityIdList);

            if (context.isEnableTrace()) {
                for (int i = 0; targetActivityIdList != null
                        && i < targetActivityIdList.size(); i++) {
                    String tmpActId = (String) targetActivityIdList.get(i);
                    ProcessTrace trace = new ProcessTrace();
                    trace.setProcessInstanceId(task.getProcess().getId());
                    trace.setStepNum(newStepNumber);
                    trace.setType(IProcessTrace.WITHDRAW_TYPE);
                    trace.setFromNodeId(tmpActId);
                    trace.setToNodeId(thisActivity.getId());
                    trace.setEdgeId("");
                    context.getPersistenceService()
                            .saveOrUpdateProcessTrace(trace);
                }
            }

            ITransition thisLeavingTransitionInstance = (ITransition) thisActivityInstance
                    .getLeavingTransitions().get(0);
            ISyncRouter synchronizerInstance = (ISyncRouter) thisLeavingTransitionInstance
                    .getLeavingNode();
            if (synchronizerInstance.getEnteringTransitions().size() > 1) {
                Token supplementToken = new Token();
                supplementToken.setAlive(false);
                supplementToken.setNodeId(synchronizerInstance.getNodeId());
                supplementToken.setProcess(task.getProcess());
                supplementToken.setFromActivityId("Empty(created by withdraw)");
                supplementToken.setStepNumber(newStepNumber);
                supplementToken.setValue(synchronizerInstance.getVolume()
                        - thisLeavingTransitionInstance.getWeight());
                persistenceService.saveOrUpdateToken(supplementToken);
            }

            Token newToken = new Token();
            newToken.setAlive(true);
            newToken.setNodeId(task.getActivityModelId());           
            newToken.setProcess(task.getProcess());
            newToken.setFromActivityId(theFromActivityIds.toString());
            newToken.setStepNumber(newStepNumber);
            newToken.setValue(0);
            persistenceService.saveOrUpdateToken(newToken);

            this.createTaskInstances(newToken, thisActivityInstance);

            List<IWorkItem>  workItems = persistenceService.findTodoWorkItems(workItem.getActorId(), 
                    task.getProcess().getDefinitionId(),
                    task.getTaskModelId());
            
            if (workItems == null || workItems.size() == 0) {
                throw new WorkflowException(
                        task.getProcess().getId(), 
                        task.getProcess().getModel(), 
                        task.getTaskModelId(),
                        "Withdraw operation failed.No work item has been created for Task[id="
                                + task.getTaskModelId() + "]");
            }
            
            if (workItems.size() > 1) {
                throw new WorkflowException(
                        task.getProcess().getId(),
                        task.getProcess().getModel(),
                        task.getTaskModelId(),
                        "Withdraw operation failed.More than one work item have been created for Task[id="
                                + task.getTaskModelId() + "]");
            }
            return (IWorkItem) workItems.get(0);
        } finally {
            setWithdrawOrRejectOperationFlag(false);
        }
    }


    public IWorkItem reassignWorkItemTo(IWorkItem workItem, String actorId,
            String comments) {
        WorkItem newWorkItem = new WorkItem();
        // TODO ...
        BeanUtils.copy(workItem, newWorkItem);
        newWorkItem.setId(null);
        newWorkItem.setActorId(actorId);
        newWorkItem.setCreatedTime(context.getCalendarService().getSysDate());
        context.getPersistenceService().saveOrUpdateWorkItem(newWorkItem);

        ((WorkItem) workItem).setState(IWorkItem.CANCELED);
        ((WorkItem) workItem).setEndTime(context.getCalendarService()
                .getSysDate());
        ((WorkItem) workItem).setComments(comments);
        context.getPersistenceService().saveOrUpdateWorkItem(workItem);
        return newWorkItem;
    }
    
    /**
     * 将TaskInstance分配给编号为actorId的操作员。即系统只创建一个WorkItem，并分配给编号为actorId的操作员<br>
     * 该WorkItem需要签收
     * @param actorId 操作员Id
     * @return  返回创建的WorkItem
     * @throws org.WorkflowException.engine.EngineException
     * @throws org.fireflow.kenel.KenelException
     */
    public IWorkItem assignToActor(ITaskInstance task, String actorId) throws WorkflowException {
        WorkItem wi = createWorkItem(task, actorId);
        return wi;
    }

    /**
     * 将TaskInstance分配给列表中的操作员。即创建N个WorkItem，每个操作员一个WorkItem，并且这些WorkItem都需要签收。<br>
     * 最终由那个操作员执行该任务实例，是由Task的分配策略决定的。<br>
     * 如果分配策略为ALL,即会签的情况，则所有的操作员都要完成相应的工单。<br>
     * 如果分配策略为ANY，则最先签收的那个操作员完成其工单和任务实例，其他操作员的工单被删除。
     * @param actorIds
     * @return  返回创建的WorkItem列表
     * @throws org.WorkflowException.engine.EngineException
     * @throws org.fireflow.kenel.KenelException
     */
    public List<IWorkItem> assignToActors(ITaskInstance task, List<String> actorIds) throws WorkflowException {
        //task应该有一个标志(asignToEveryone)，表明asign的规则 (?)
        List<IWorkItem> workItemList = new ArrayList<IWorkItem>();
        for (int i = 0; actorIds != null && i < actorIds.size(); i++) {
            WorkItem wi = createWorkItem(task, actorIds.get(i));
            workItemList.add(wi);
        }
        return workItemList;
    }

}
